Comparing to a string literal in a console application - c++

I have a simple native C++ console app.
I want to stay something like this:
Quit? (Y/N)
and be able to type in Y or N to tell the program what to do?
So far I have this code:
std::string whetherToQuit;
std::cout<<"Quit? (Y/N): ";
std::cin>>whetherToQuit;
if(whetherToQuit == "Y"){
exit(EXIT_SUCCESS);
}
else if (whetherToQuit == "N"){
break;
}
MSVC++ gives me a warning and I think there should be a better way to do this.
If it matters I am using Windows.
Any suggestions?

Why not use a char instead:
char ans;
std::cout << "Quit? (Y/N): ";
std::cin >> ans;
if (ans == 'Y') {
return 0;
}
else if (ans == 'N') {
break;
}

There are three points worth mentioning:
Why are you using string? Use char instead:
char ans;
if (ans == 'Y') {
// op
}
else if (ans == 'N') {
// op
}
Why are you using "break" inside else if. A break statement may only be used within a switch or loop.
[ADDED] Use return instead of Exit. Exit circumvents RAII.
Final code should look like
char ans;
std::cout << "Quit? (Y/N): ";
std::cin >> ans;
if (ans == 'Y') {
return 0;
}
else if (ans == 'N') {
// No op;
}

What does the warning message say?
You can do like this:
const std::string strYes = "Y";
const std::string strNo = "N";
and then compare with this constants.

Related

how do you define an exact case constant with a switch statement in c++

I'm learning C++ and I don't fully understand how case works in switch statements. I have the following code:
bool accept3() {
int tries = 1;
while (tries<4) {
std::cout<<"Do you want to proceed (y or n)?\n";
char answer = 0;
std::cin>>answer;
switch(answer) {
case 'y':
return true;
case 'n':
return false;
default:
std::cout<<"Sorry, but I don't understand that.\n";
tries ++;
}
}
std::cout << "I'll take that as a no.\n";
return false;
}
int main()
{
//accept();
//accept2();
accept3();
}
It works as expected when you input, 'y', 'n', or any other single character that does not meet the two defined cases.
When you input any string of characters that begins with n, it still takes that as the 'n' case. Why does it do this? How can I make this more exact, so that it ONLY accepts 'n' and not 'no', 'no way' or any other string beginning with 'n'.
Thank you!
This is tricky because if you input text with spaces into the terminal, like "d d d y", then you'll see the loop trigger 4 times in a row because "cin >> answer" breaks the line into separate inputs (this is called tokenization).
Here's code demonstrating how to properly parse an entire line of input as one menu command:
#include <iostream>
#include <string>
bool accept3() {
int tries = 1;
while (tries < 4) {
std::cout << "Do you want to proceed (y or n)?\n";
std::string answerStr;
std::getline(std::cin, answerStr);
char answer = '\0';
if (answerStr.size() == 1) {
answer = answerStr[0];
}
switch (answer) {
case 'y':
return true;
case 'n':
return false;
default:
std::cout << "Sorry, but I don't understand that.\n";
tries++;
}
}
std::cout << "I'll take that as a no.\n";
return false;
}
int main()
{
//accept();
//accept2();
accept3();
}
When you input any string of characters that begins with n, it still takes that as the 'n' case. Why does it do this?
Because you are asking cin to read a single char, so that is what it does. operator>>(char&) ignores leading whitespace, if any, and then reads 1 char. Any subsequent characters, if any, are left in the input buffer for later reads.
How can I make this more exact, so that it ONLY accepts 'n' and not 'no', 'no way' or any other string beginning with 'n'.
Use cin.getline() or std::getline() instead, and then compare the entire line, eg:
bool accept3() {
int tries = 1;
std::string answer;
do {
std::cout << "Do you want to proceed (y or n)?\n";
std::getline(std::cin >> std::ws, answer);
if (answer == "y")
return true;
if (answer == "n")
return false;
std::cout << "Sorry, but I don't understand that.\n";
++tries;
}
while (tries < 4);
std::cout << "I'll take that as a no.\n";
return false;
}

Changed if - if functions to if - else, and I get "else without previous if" [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed last year.
Improve this question
Recently I have been making a text-based game to imitate a game from the 90's for my friend, and it went all well, but the Yes/No didn't work because I had an if statement then another if statement following first, so then I change it to an if statement with an else statement following the if statement, but get error's like "else without previous if" and "label referenced but not defined" which is really weird because a few lines below the reference in the defined label... I really need help with this, because I tried googling it but comes up with useless Microsoft threads that don't relate whatsoever.
My Code:
#include <iostream>
int main() //main function
{
std::cout << "NOTE: when you see [Y/N], it is a choice option, please capitalize letter of choice!!\n";
lab1:
char name = NULL;
int age = NULL;
char ans1 = NULL;
char strong = NULL;
char ans2 = NULL;
char ans3 = NULL;
char smart = NULL;
char ans4 = NULL;
char ans5 = NULL;
std::cout << "Well hello! What is your name?\n";
std::cin >> name;
std::cout << "And your age is?\n";
std::cin >> age;
std::cout << "Ok so your name is " << name << " and you are " << age << "?\n";
std::cout << "Is that correct? [Y/N]\n";
std::cin >> ans1;
if (ans1 == 'Y');
{
std::cout << "Well then, lets get started with your main ability!\n";
goto lab2;
}
else
{
std::cout << "Oh sorry, my bad lets enter it again shall we?\n";
goto lab1;
}
lab2:
lab4:
lab6:
std::cout << "Strong? [Y/N]\n";
std::cin >> strong;
if (strong == 'Y');
{
std::cout << "Are you sure? Only ONE main ability can be chosen! [Y/N]\n";
std::cin >> ans2;
if (ans2 == 'Y')
{
goto lab3;
}
else
{
goto lab4;
}
}
else
{
std::cout << "Are you sure? Move to next ability? [Y/N]\n";
std::cin >> ans3;
if (ans3 == 'Y');
{
goto lab5;
}
else
{
goto lab6;
}
}
lab5:
lab8:
lab10:
std::cout << "Smart? [Y/N]\n";
std::cin >> smart;
if (smart == 'Y')
{
std::cout << "Are you sure? Only ONE main ability can be chosen! [Y/N]\n";
std::cin >> ans4;
if (ans4 == 'Y')
{
goto lab7;
}
else
{
goto lab8;
}
}
else
{
std::cout << "Are you sure? Move to next ability? [Y/N]\n";
std::cin >> ans5;
if (ans5 == 'Y')
{
goto lab9;
}
else
{
goto lab10;
}
}
lab9:
lab3:
lab7:
std::cout << "Done!";
}
I know this doesnt answer your question but I am going to give advice.
Code like this with that many labels is very fragile (meaning its hard to change as your project grows). I have worked on large c++ projects (100,000 lines +) and every goto and label had to be individually justified. Many probably had none. You should develop a dislike of typing the characters 'g' 'o' 't' 'o'.
So how do you do what you code is trying to do. The common idiom is
std::string ans;
while(true)
{
std::cout >> "Are you sure";
std::cin >> ans;
if(ans == "Y" || ans == "N")
break;
}
if (ans == "Y")
{
//do the yes thing
}
else
{
// do the no thing
}
This will keep looping , asking the user a Yes No question until they answer Y or N
Taking your example of Smart
bool isSmart = false;
while(true)
{
std::cout << "Smart? [Y/N]\n";
std::cin >> smart;
if (smart == 'Y')
{
std::cout << "Are you sure? Only ONE main ability can be chosen! ";
std::cin >> ans4;
if (ans4 == 'Y')
{
isSmart = true;
break;
}
}
}
EDIT, answer the original question
You have
if (ans3 == 'Y');
{
goto lab5;
}
else
{
goto lab6;
}
this is invalid syntax
you need
if (ans3 == 'Y') // <=== no ;
{
goto lab5;
}
else
{
goto lab6;
}
You have this same error in multiple places

Having to hit enter twice with cin.getline()

I know for a fact similar questions have been asked before but I really can't figure out what's wrong with my code specifically. For some reason if I input "n" I have to press enter twice. But if I input "y", everything works fine and the code moves to the next section. My code is as follows:
do{
try {
if (test) cout << " Re-enter: ";
test = false;
getline(cin, choice);
checkinput(choice);
}
catch (int flag) {
if (flag == 1){ cout << "Error: Input must be y or n."; test = true; }
}
} while (test);
and the checkinput function is as follows:
// function for checking the input of y/n
string checkinput(string c) {
if (c != "Y" && c != "y" && c != "N" && c != "n") {
throw 1;
}
if (cin.fail()) throw 1;
return c;
}
I think you are trying to do too much here. You can simplify this.
There is no need to throw and catch exceptions inside checkinput. Since there is only two cases you can use a boolean. Secondly, you are returning c. I don't know why you are doing that, it isn't being used. You should instead, return a boolean.
checkinput becomes:
bool checkInput(string c) {
if (c.length() > 1)
return false;
return c == "Y" || c == "y" || c == "N" || c == "n";
}
Now you can simplify the do-while and remove the try statement. Additionally, there is no need for the test variable now since we are successfully grabbing any input:
int main() {
string choice = "";
do {
cout << "Enter yes or no (y/n): ";
getline(cin, choice); // or cin >> choice;
bool check = checkInput(choice);
if (!check)
cout << "Error: Input must be y or n." << endl;
} while (true);
}
You may also simplify this further but that will be at the cost of readability. Good luck!

Get yes/no in console always fails

I'm trying to make a program that will run over and over again, provided the user says yes every time. Unfortunately, it doesn't seem to recognize when I input yes or no into it, and always does the default "Come again?" message. This is the code I'm using to get the input from the console:
bool getYN(){
bool confirmed = 0;
bool answer = 0;
string input;
while(!confirmed){
getline(cin, input, '\n');
transform(input.begin(), input.end(), input.begin(), toupper);
if(input.c_str() == "Y" || input.c_str() == "YES"){ //If the user says yes
confirmed = 1;
answer = 1;
} else if(input.c_str() == "N" || input.c_str() == "NO"){ //If the user says no
confirmed = 1;
answer = 0;
} else { //If the user says something else entirely
printf("\nCome again? (Y/N) ");
};
};
return answer;
};
I have included <string> and <algorithm>. For some reason, it always acts like it's not getting y/yes or n/no when I type them in. It just keeps asking me to answer again.
if(input.c_str() == "Y" || input.c_str() == "YES"){ //If the user says yes
confirmed = 1;
answer = 1;
} else if(input.c_str() == "N" || input.c_str() == "NO"){ //If the user says no
confirmed = 1;
answer = 0;
}
You should not be doing c-string comparisons like this. You're taking the address of a char and comparing against the address of a text-allocated object. Of course the comparison is going to return false.
With c++ strings, simple operator== comparisons are valid:
if(input == "Y" || input == "YES"){ //If the user says yes
confirmed = 1;
answer = 1;
} else if(input == "N" || input == "NO"){ //If the user says no
confirmed = 1;
answer = 0;
}
#include <iostream>
#include <string>
using namespace std; // For speed
int main()
{
bool saidYes = false;
string input;
while (!saidYes)
{
cout << "Input yes or no: ";
getline(cin, input);
if (input == "no" || input == "n" || input == "NO")
{
saidYes = true; // breaks the loop
}
if (input == "y" || input == "Y" || input == "yes" || input == "YES")
{
saidYes = false;
}
}
return 0;
}
You can use the above example to eliminate a huge portion of unnecessary code, I chose not to add the else statement but it will work if you add that here as well.
You can also condense this code even further but this was only intended to be a simple example as to how to better get this working for you!
As it was said above you can use == to compare the strings, if you're coming from certain other languages it can be an annoying change to get used to lol.
I have included string and algorithm. For some reason, it always acts like it's not getting y/yes or n/no when I type them in. It just keeps asking me to answer again.
algorithm is not required for what you're trying to do, and your making the reading and acceptance of the string input much more difficult than it needs to be.
If you look above you'll see the string input; This is going to be your variable that you can use to store the user input string into.
You'll also notice getline(cin, input); This is what you can use to "read" the string that the user enters when they're prompted to.
#Kelvin Shadewing My initial answer was only directed at your Question, this next example is directed to your comment to me below!
So you've got quite a few options but assuming that you want the user to input either yes or no and depending on the input you want to produce a specific result while ensuring that the user is prompted over and over again to input either yes or no all you have to is modify my original answer like so.
#include <iostream>
#include <string>
using namespace std; // For speed
int main()
{
bool saidYes = false;
string input;
while (!saidYes)
{
cout << "Input yes or no: ";
getline(cin, input);
if (input == "no" || input == "n" || input == "NO")
{
saidYes = true;
cout << "you said no" << endl;
/* breaks the loop by changing the
bool (true or false flag) to true, if you want to produce a specific result,
whether it's a simple output statement or a function call you can put it here
*/
}
else if (input == "y" || input == "Y" || input == "yes" || input == "YES")
{
saidYes = true;
cout << "You said yes" << endl;
/* breaks the loop by changing the
bool (true or false flag) to true, if you want to produce a specific result,
whether it's a simple output statement or a function call you can put it here
*/
}
else saidYes = false;
}
return 0;
}
I've modified my code based on the current best answer, but I've also optimized it so that confirmed is no longer necessary.
bool getYN(){
bool answer = 0;
string input;
while(!answer){
getline(cin, input, '\n');
transform(input.begin(), input.end(), input.begin(), toupper);
if(input == "Y" || input == "YES"){
answer = 2;
} else if(input == "N" || input == "NO"){
answer = 1;
} else {
printf("\nCome again? (Y/N) ");
};
};
return answer - 1;
};
Small optimization, sure, but every little bit counts.

How do I allow different amounts of input in c++

Assume all variables exist (didnt bother declaring them all here)
if(input=='R') goto restart;
if(input=='X') exit(0);
if(input=='D') moveRight(edgeLength, board, score);
if(input=='S') moveDown(edgeLength,board, arrSize);
if(input=='A') moveLeft(edgeLength,board, arrSize);
if(input=='W') moveUp(edgeLength,arrSize,board);
if(input=='P')
{
cin>> number>>position;
board[position]=number;
}
This input is put into a loop, so the user is asked for input so long as this game is in play.
My goal is to allow for input such as
p 3 50
to place the number 50 at index position 3.
With my current code, I have to type 'p' press enter, then the next two numbers.
However, id like the program to detect 'p 3 50' (enter) in one go, as 'D'(enter) signifies moveRight.
I hope I'm being clear in my question.
cin >> input >> number >> position;
if(input=='R') goto restart;
else if(input=='X') exit(0);
else if(input=='D') moveRight(edgeLength, board, score);
else if(input=='S') moveDown(edgeLength,board, arrSize);
else if(input=='A') moveLeft(edgeLength,board, arrSize);
else if(input=='W') moveUp(edgeLength,arrSize,board);
else
{
//whatever statements for last condition;
}
If you want to capture all three input at once, you can get the input first, then execute the respective actions according to the received inputs.
Added: Using if or else-if depends on situation. From what I see here in your code snippet, else-if is better than if because you can only have one input type everytime. Once matching character is found, (example 'D'), it will stop reading the codes below (which should be the way as it is unnecessary to check the rest of the conditions whether input is 'S' or 'A' or 'W' anymore since you already got the input). Makes your code fun slightly faster too, by preventing unnecessary checking on the conditions.
Proof Of Concept:
//Example
void fncOne()
{
cout << "This is function one" << endl;
}
void fncTwo()
{
cout << "This is function two" << endl;
}
int main()
{
char input;
int number, position;
cin >> input >> number >> position;
if (input == 'A') fncOne();
else if (input == 'B') fncTwo();
}
Input: A 3 5
Output: This is function one
Well, first you're going to want to get user input as a string rather than individual types.
std::string input;
std::cin >> input;
then you'll want to parse that string based on how many words for key words/characters.
e.g.
std::vector<std::string> words;
std::stringstream stream(input); std::string temp;
while(stream >> temp)
words.push_back(temp);
if(words.size() == 3){
if(words[0][0] = 'p'){
int number = std::stoi(words[1]);
int position = std::stoi(words[2]);
board[position] = number;
}
else
... get input again ...
}
else if(words.size() > 1){
... get input again ...
}
else{
char c = words[0][0];
if(c == 'w')
moveUp(edgeLength,arrSize,board);
else if(c == 's')
moveDown(edgeLength,board, arrSize);
else if(c == 'a')
moveLeft(edgeLength,board, arrSize);
else if(c == 'd')
moveRight(edgeLength, board, score);
else if(c == 'x')
exit(0);
else if(c == 'r')
goto restart;
else
... get input again ...
}
Of course this is only one way if you want to type one string then press enter only once.