I am working on a project right now and when I try to run what I have below it gives me an error that says "uninitialized local variable 'userOption' used" on line 22, while (isValidOption(userOption) == true) {.
How do I fix that error? Thank you.
#include<iostream>
#include <string>
using namespace std;
char toupper(char ch) {
if (ch >= 'A'&&ch <= 'Z')
return(ch);
else
return(ch - 32);
}
bool isValidOption(char ch) {
if (ch == 'I' || ch == 'O' || ch == 'L' || ch == 'X')
return(true);
else
return(false);
}
char getMainOption() {
string UserInput;
char userOption;
while (isValidOption(userOption) == true) {
cout << "Choose One of the following options\n";
cout << "I--List Our Inventory\n";
cout << "O--Make an Order\n";
cout << "L--List all Orders made\n";
cout << "X--Exit\n";
cout << "Enter an option: ";
getline(cin, UserInput);
userOption = toupper(UserInput[0]);
if (!isValidOption(userOption)) {
cout << "Invalid String\n";
cout << "Enter an option: ";
getline(cin, UserInput);
userOption = toupper(UserInput[0]);
}
if (userOption == 'I')
cout << "Listing Our Inventory\n";
else if (userOption == 'O')
cout << "Make an order\n";
else if (userOption == 'L')
cout << "Listing all orders\n";
}
return userOption;
}
int main() {
char choice;
choice = getMainOption();
system("pause");
return 0;
}
What the error is saying that you're trying to read from userOption before you've ever written to it. If a variable is uninitialized, its memory contents will be full of junk left behind by other functions and it can easily cause bugs. In your case, you'll want to read input from the user into userOption before you do any logic on it. This can be done with a do-while loop:
char userOption; // not yet initialized
do {
...
cin >> userOption; // userOption gets initialized here on first loop run
} while (isValidOption(userOption)); // no need for == true, that's a tautology :-)
// NOTE: perhaps you want to loop while the input is INvalid, as in
// while (!isValidOption(userOption)); ?
A couply code-review comments I would additionally give are:
std::toupper already exists in <cctype>. Docs are here
return is not a function call and it's better to write return ch; than return(ch);
if (ch == 'I' || ch == 'O' || ch == 'L' || ch == 'X'){ return true; } else { return false; } is completely equivalent to the shorter return ch == 'I' || ch == 'O' || ch == 'L' || ch == 'X';
Also take a look at system(“pause”); - Why is it wrong?
Happy coding! Let me know if questions remain
Related
I just want to read every character in a file where I put characters from A TO Z but the program prints A every time and count vowels 4 and character 25 but expectation was to printing vowels 5 and characters 26 how to fix this program fixing from last 4 hours but nothing progress?
Code:
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main() {
int i, count = 0, vowel_count = 0;
string file_name;
cout << "enter file name:";
cin >> file_name;
ifstream fin;
fin.open(file_name);
char ch;
while (!fin.eof()) {
fin.get(ch);
cout << ch;
while (fin >> ch) {
i = ch;
if ((i > 63 && i < 91) || (i > 96 && i < 123))
count++;
if (i == 'a' || ch == 'A' || ch == 'e' || ch == 'E' || ch == 'i' || ch == 'I' || ch == 'o' || ch == 'O' || ch == 'u' || ch == 'U')
vowel_count++;
}
cout << "\n No. of Characters in a File : " << count;
cout << "\n No. of vowel characters in the File : " << vowel_count;
}
fin.close();
return 0;
}
You have some really minor erros in the code, which I fixed for you.
Additionally, I added a check, if the file could be opened or not. That is the problem in most cases.
Please see below:
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main() {
int count = 0, vowel_count = 0;
string file_name;
cout << "\nEnter file name: ";
cin >> file_name;
ifstream fin(file_name);
if (fin) {
char ch;
while (fin.get(ch)) {
cout << ch;
if ((ch >= 'A' && ch <= 'Z') || (ch > 'a' && ch <= 'z'))
count++;
if (ch == 'a' || ch == 'A' || ch == 'e' || ch == 'E' || ch == 'i' || ch == 'I' || ch == 'o' || ch == 'O' || ch == 'u' || ch == 'U')
vowel_count++;
}
fin.close();
cout << "\n No. of Characters in a File : " << count;
cout << "\n No. of vowel characters in the File : " << vowel_count;
}
else std::cerr << "\n\n*** Error. Could notopen '" << file_name << "'\n\n";
return 0;
}
basically I am having weird trouble with my while loop near the beginning of the program which checks for user validation on their choice of activity. When they choose the first activity and complete it, it works fine, but when they complete the second activity, it will go into runtime and keep requesting the user to input a valid choice, even though they haven't even gotten the chance to input a choice. Any tips?
#include <iostream>
using namespace std;
int main()
{
const int DIGITS_CHOICE = 1, IDENTIFIER_CHOICE = 2, DOUBLE_CHOICE = 3, EXIT_CHOICE = 4;
int choice;
int userNumber, storedNumber, factor = 10, digitCounter = 0, subtractor;
char ch;
do
{
cout << "\n\n\t\tPlease choose an option:\n\n"
<< "1. How many digits?\n"
<< "2. Is this a valid C++ Identifer?\n"
<< "3. Is this a double letter word?\n"
<< "4. Exit\n";
cout << endl << "Choice: ";
cin >> choice;
while (choice < DIGITS_CHOICE || choice > EXIT_CHOICE)
{
cout << endl << "Please enter a valid menu option: ";
cin >> choice;
}
if (choice != EXIT_CHOICE)
{
switch (choice)
{
case DIGITS_CHOICE:
cout << "Please enter an integer: ";
cin >> userNumber;
storedNumber = userNumber;
if (userNumber < 10)
{
digitCounter = 1;
}
else
{
while (userNumber != 0)
{
subtractor = userNumber % factor;
if (subtractor > 0)
{
userNumber = userNumber - subtractor;
factor *= 10;
digitCounter++;
}
else
{
userNumber = 0;
}
}
}
cout << storedNumber << " has " << digitCounter << " digit(s)." << endl;
factor = 10;
digitCounter = 0;
break;
case IDENTIFIER_CHOICE:
cout << "Please enter an identifier and press [Enter] immediately after. ";
cin >> ch;
if (ch >= 0 || ch <= 9 || ch <= 'a' || ch >= 'z' || ch <= 'A' || ch >= 'Z' || ch != '_')
{
if (ch >= 0 || ch <= 9)
{
cout << "Not a valid identifier." << endl;
cout << "Identifiers cannot start with a digit." << endl;
ch = '\n';
}
else
{
cout << "Not a valid identifier." << endl;
cout << "Inavlid character." << endl;
ch = '\n';
}
}
while (ch != '\n')
{
if (ch >= 'a' || ch <= 'z' || ch >= 'A' || ch <= 'Z')
{
cin.get(ch);
}
}
break;
case DOUBLE_CHOICE:
break;
}
}
} while (choice != EXIT_CHOICE);
return 0;
}
Also the program isn't complete yet. the third option has nothing and the 2nd option is almost complete. the first activity though is complete :)
Your check for valid characters is too broad, and doesn't really make sense:
if (ch >= 0 || ch <= 9 || ch <= 'a' || ch >= 'z' || ch <= 'A' || ch >= 'Z' || ch != '_')
Every possible value of ch is going to be greater than or equal to zero, so this expression is equivalent to (true || a || b || c || ... || z) and it's always going to resolve to true.
Instead, see if it's below 'A', between 'Z' and 'a' or beyond 'z' and if so, it's invalid.
Also, when checking if it's a digit, you need to check if it's ≥ '0' and ≤ '9' as characters. It's important that you compare it to the character representation of 0 and 9 because the value of the character '0' not actually 0 (it turns out it's actually 48) and likewise with '9':
if ( ch < 'A'
|| (ch > 'Z' && ch < 'a')
|| ch > 'z')
{
if (ch >= '0' && ch <= '9')
{
cout << "Not a valid identifier." << endl;
cout << "Identifiers cannot start with a digit." << endl;
ch = '\n';
}
else
{
cout << "Not a valid identifier." << endl;
cout << "Invalid character." << endl;
ch = '\n';
}
}
It's not really clear what the check after that is meant to do? Is it only meant to allow letters? That seems strange after saying "Identifiers cannot start with a digit." anyway:
if (ch >= 'a' || ch <= 'z' || ch >= 'A' || ch <= 'Z')
This has essentially the same issue where every character is going to be either above 'a' or below 'z' or both, so this will always resolve to true. Instead, use && to check for being within a range:
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
Hopefully that addresses your question.
The logic is not great; i is valid, but your code says it's not. It at least goes back to the menu just fine. Your code is also behaving like it will respond immediately as letters are being typed. That is not the case. It won't print anything until the user presses Enter.
It seems the issue is your variable ch being a char. If I type anything that's longer than a single character, what will happen is that the single character gets evaluated, and the remaining characters I typed remain in the input stream. It looks like you are attempting to handle that, but it's not working. I am not going to spend time delving into the why, partly because it's complex, partly because I don't know the full intricacies of istream behavior.
What I will say is that if you want to handle a multi-character input, use cin.get() everywhere and not just sometimes. You can do processing of each character, but again, nothing will go to the screen until the user presses Enter.
But here's code that appears to work:
#include <cctype> // isalpha() and isalnum()
#include <string> // ch is now a std::string
// ...
case IDENTIFIER_CHOICE:
cout << "Please enter an identifier and press [Enter] immediately after. ";
std::cin.ignore(256, '\n'); // needed because of getline behavior
std::getline(std::cin, ch);
if (!(isalpha(ch[0]) || ch[0] == '_')) {
cout << "Not valid.\n";
break;
}
for (int i = 1; i < ch.size(); ++i) {
if (!isalnum(ch[i])) {
cout << "Not valid.\n";
break;
}
}
cout << "Valid.\n";
break;
// ...
With cin, when you press Enter, that keystroke is saved in the input stream. getline() doesn't behave the way we expect because while cin will typically ignore that keystroke, getline does not. So I just tell cin to ignore an arbitrary (but sufficient in this case) amount of characters in the stream up to and including the Enter keystroke (Mac and Linux, should still behave for Windows (I think)).
This is still far from bulletproof input validation (that's impossible), but I think it suffices for what you're working on.
This code is replacing all the characters. Not just vowels. What am I doing wrong?
using namespace std;
bool isVowel(char);
int main() {
string fName = "";
string lName = "";
cout << "Enter first name: " << endl;
cin >> fName;
cout << "Enter last name: " << endl;
cin >> lName;
string name = fName + " " + lName;
cout << name << endl;
for(int i = 0; i < name.length(); i++) {
if(isVowel(name.at(i))) {
name[i] = 'z';
}
}
cout << name << endl;
}
bool isVowel(char c) {
if(c == 'a' || 'e' || 'i' || 'o' || 'u' || 'A' || 'O' || 'E' || 'I' || 'U') {
return true;
}
else {
return false;
}
}
I did some research online and I think my problem lies in that I am passing the character as a reference? I didn't understand how that could be...
The isVowel() function checks if the char is a vowel I think that's where the problem lies, since the program is replacing all the characters I'm assuming that function is not working.
you need to put your if statement as (c == 'a' || c == 'e' || c == 'i'..., the way it is written currently it casts all of the characters on their own as boolean expressions.
The program will ask user to input strand which has to be composed of only ABCD and if the input contains letter other than ABCD it must show error, otherwise it should output "ok!"
string strand1;
again:
cout << "Enter String 1:\n";
cin >> strand1;
for (int i = 0; i <= strand1.length(); i++)
{
if (strand1.at(i) != 'A'&&strand1.at(i) != 'B'&&strand1.at(i) != 'C'&&strand1.at(i) != 'D')
{
cout << "Invalid Input";
system("cls");
goto again;
}
else
{
i++;
}
}
cout << "ok";
_getch();
return 0;
Move the necessary checks to a function -- isValidInput.
Use hand coded logic to check whether the input is valid or use the standard library function std::find_if to do the same.
Use the function in a while loop in the main function.
bool isNotABCD(char c)
{
return !((c == 'A') || (c == 'B') || (c == 'C') || (c == 'D'));
}
bool isValidInput(std::string const& str)
{
return (std::find_if(str.begin(), str.end(), isNotABCD) == str.end());
}
int main()
{
string strand1;
cout << "Enter String 1:\n";
while ( cin >> strand1 && !isValidInput(strand1) )
{
cout << "Invalid Input";
system("cls");
cout << "Enter String 1:\n";
}
cout << "ok";
}
Update
You can also use a simpler version of isValidInput(), Thanks to #Blastfurnace for the suggestion.
bool isABCD(char c)
{
return (c == 'A') || (c == 'B') || (c == 'C') || (c == 'D');
}
bool isValidInput(std::string const& str)
{
return (std::all_of(str.begin(), str.end(), isABCD));
}
Update 2
You can also use a still simpler version of isValidInput(), Thanks to #JorenHeit for the suggestion.
bool isValidInput(std::string const& str)
{
return (std::find_first_not_of("ABCD") == std::string::npos);
}
Your question is unclear, but after examining your code I believe the problem is that for your loop condition you are using i <= strand1.length when you should be using i < strand1.length.
The loop condition you are using will check an index out of bounds of the string. In addition, you should not be incrementing i in the else statement as that is already done in the for statement. In the future, please clearly state your question along with any error codes you are getting.
This program basically just checks that a statement (mathematical) is properly constructed considering the brackets, parenthesis, and curly-braces. It uses a stack to compare the most recently read delimiter to see if the ending type of that delimiter exists, otherwise it says it is not constructed properly. I'm stuck, as it always returns that the statement is incorrect. This is what I have so far:
#include <iostream>
#include <stack>
using namespace std;
bool delimiterMatching(char* file);
void main(){
char fileName[50];
cout << "Enter a statement (Ex. s=t[5]+u/(v*(w+y)); : ";
cin >> fileName;
cout << endl;
if(delimiterMatching(fileName))
cout << endl << "Your statement was constructed successfully." << endl;
else cout << endl << "Your statement is incorrectly constructed." << endl;
}
bool delimiterMatching(char* file){
stack<char> var;
int counter = 0;
char ch, temp, popd;
do{
ch = file[counter];
if(ch == '(' || ch == '[' || ch == '{')
var.push(ch);
else if(ch == '/'){
temp = file[counter+1];
if(temp == '*')
var.push(ch);
else{
ch = temp;
continue;
}
}
else if(ch == ')' || ch == ']' || ch == '}'){
popd = var.top();
var.pop();
if(ch != popd)
return false;
}
else if(ch == '*'){
temp = file[counter+1];
popd = var.top();
var.pop();
if(temp == '/' && popd != '/')
return false;
else{
ch = temp;
var.push(popd);
continue;
}
}
counter++;
}while(ch != '\n');
if(var.empty())
return true;
else return false;
}
I've already tried googling for some hints, but got nothing too helpful. I debugged it, and if I use "s=t[5]+u/(v*(w+y));", when it reads the second bracket after the 5, it obviously isn't the same char. So how do I compare the opening symbol with the ending symbol?
I appreciate any help. I'll edit this/comment it if I figure it out myself. Thanks for your time!
I got it working this is the final code:
#include <iostream>
#include <stack>
using namespace std;
bool delimiterMatching(char* file);
void main(){
char fileName[50];
cout << "Enter a statement (Ex. s=t[5]+u/(v*(w+y)); : ";
cin >> fileName;
cout << endl;
if(delimiterMatching(fileName))
cout << endl << "Your statement was constructed successfully." << endl;
else cout << endl << "Your statement is incorrectly constructed." << endl;
}
bool delimiterMatching(char* file){
stack<char> var;
int counter = 0;
char ch, temp, popd;
do{
ch = file[counter];
if(ch == ';')
break;
if(ch == '(' || ch == '[' || ch == '{')
var.push(ch);
else if(ch == '/'){
temp = file[counter+1];
if(temp == '*')
var.push(ch);
else{
counter++;
continue;
}
}
else if(ch == ')' || ch == ']' || ch == '}'){
popd = var.top();
var.pop();
if((ch==')' && popd!='(') || (ch==']' && popd!='[') || (ch=='}' && popd!='{'))
return false;
}
else if(ch == '*'){
temp = file[counter+1];
popd = var.top();
var.pop();
if(temp == '/' && popd != '/')
return false;
else{
counter++;
var.push(popd);
continue;
}
}
counter++;
}while(ch != '\n');
if(var.empty())
return true;
else return false;
}
Your checking if the closing bracket (eg. ')', ']' or '}') matches the value popped off the stack. They are never going to be equal because you are only pushing the left sides of the brackets ('(', '[' or '{'), while comparing it with the right side of the brackets.
It should look something like this:
else if(ch == ')' || ch == ']' || ch == '}'){
popd = var.top();
var.pop();
if((ch==')' && popd!='(') || (ch==']' && popd!='[') || (ch=='}' && popd!='{'))
return false;
}