C++ string variables with if statements - c++

I've tried re-defining these variables in every imaginable way possible
to try and get this line to work. I'm just going to give one example
here to represent what's troubling me.
double const FRAME_COST = 45.00;
string input;
char yes,
no;
int frames;
cout << "Do you want additional frames? Type yes/no: ";
cin >> input;
if (input == yes){
cout << "How many?"
cin >> frames;
frames = frames * FRAME_COST;
}
// The problem is in **the if statement**
// I need to use a string not a bool (according to my professor)
// I can't get the compiler to recognize the **if statement**
// I realize this isn't practical, but he always throws curve balls.

Your current program has undefined behavior, because yes and no are character variables that have not been initialized, and you are using one of them in a comparison.
To fix, remove the declarations of yes and no (you do not need them), and use a string literal instead:
if (input == "yes") {
...
}
Note: your comparison may be too strict, because it is case-sensitive. It will take a yes, but it would not take a Yes or a YES as an answer. To address this you may want to convert the input string to lower case before the comparison.

const string YES = "yes";
const string NO = "no";
const double FRAME_COST = 45.0;
int main()
{
string input;
double frames;
cout << "Hello World" << endl;
cin >> input;
if(input == YES)
{
cout << "How many?" << endl;
cin >> frames;
frames = frames * FRAME_COST;
cout << frames << endl;
}
return 0;
}

Just having a char named "yes" and another char name "no" is not sufficient, especially as you never actually gave them any values. I think you meant to write:
if (input == "yes") {

input == yes needs to be input == "yes" the quotes let the compiler know it's a string and not an identifier. I also think this might be helpful.

You need to do the comparison with a string or character array.
if (input == yes)
This line does nothing as yes is a character pointer that is never initialized. It should be
if (input == "yes")
And you do not need the yes variable (alternatively, you can declare a constant string with the values to check: e.g. const std::string YES("yes");)
Note, you should probably also account for case-sensitivity.
Additionally, you are multiplying an integer frames by a double FRAME_COST (presumably to get the total cost?). This will result in a truncated integer value since you are storing it in an int. If you want the cost to be in dollars and cents, you should store it in a double or float:
double cost = frames * FRAME_COST;

yes and no should be string constants (if you want to make them perfectly match with the input), either const std::string or const char* (or auto) but you have to assigh a value.
double const** FRAME_COST = 45.00;
string input;
const char* yes = "yes"
const char* no = "no";
int frames;
cout << "Do you want additional frames? Type yes/no: ";
cin >> input;
if (input == yes){ // exact comparison (maybe add a space trim of input?)
cout << "How many?"
cin >> frames;
frames = frames * FRAME_COST;
}

Instead of creating an if statement for only one input, is there a way of doing it with multiple inputs for one if statement without having to create several if statements?
for example...
string input;
cout << "Are you Bob?";
if (input == "yes", "no", "maybe"){
cout << "Sure...";
}else {
cout << "CANNOT COMPUTE";
}
Every time I try this, the input can be anything, and it will act as if I said "yes", "no", or "maybe".

#include <iostream>
#include<cmath>;
using namespace std;
int main()
{
double const FRAME_COST = 45.00;
string input;
int frames;
cout << "Do you want additional frames? Type yes/no: ";
cin >> input;
if (input == "yes"){
cout << "How many?";
cin >> frames;
frames = frames * FRAME_COST;
cout<<frames<<endl;}
else
{cout<<"please enter yes for additional frames";
}
//ALL ERRORS ARE SOLVED;
//ENJOY
//FOR MORE HELP YOU CAN CONTACT ME WHATSAPP +923034073767.
// The problem is in **the if statement**
// I need to use a string not a bool (according to my professor)
// I can't get the compiler to recognize the **if statement**
// I realize this isn't practical, but he always throws curve balls.
return 0;
}

Related

C++ How do I compare a 'int' or 'double' to a char using ASCII code? Is it possible? [duplicate]

I am trying to get input from the user and need to know a way to have the program recognize that the input was or was not a double/char this is what i have right now... but when you type an incorrect type of input
1) the double test one just loops infinatly
2) the char one won't stop looping even with the correct imput
int main () {
double _double = 0;
bool done = true;
while ( done ) {
cout << "Please enter a DOUBLE:\n" << endl;
cin >> _double;
if ( _double > 0 ) { done = false; }
if ( _double < 0 ) { cout << "\nthe number you entered was less than zero\nplease enter a valad number..." << endl; }
if(cin.fail()) { cin.clear(); }
}
done = false;
char _char = ' ';
while ( !done ) {
cout << "Please enter a CHAR" << "\n";
cout << "\t'y' = yes\n\t'n' = no" << endl;
cin >> _char;
if ( _char == 'y' || _char == 'n' ) { done = true; }
if ( ! (_char == 'y' || _char == 'n') ) { cout << "\nyou have entered an invald symbol... \n" << endl; }
if(cin.fail()) { cin.clear(); }
}
The best bet is always to read your input as strings. You can then use functions like std::strtod() to test and convert to doubles. Checking if streams have failed and then resetting them is error prone at best, and doesn't give you the possibility of producing good error messages.
For example:
string s;
cin >> s;
char * p;
double d = strtod( s.c_str(), & p );
if ( * p == 0 ) {
cout << "Read double: " << d << endl;
}
else {
cout << "Read string: " << s << endl;
}
The pointer 'p' will point to the first character that cannot be converted to a double. How exactly you handle that really depends on your app's logic.
The problem is that when you read something and cin sees the input can never be a double, it stops reading, leaving the stuff in the buffer that it didn't consume. It will signal failure, which you clear but you won't eat the remaining input that cin didn't eat up. So, the next time the same wrong input is tried to read again, and again...
The problem with the char one is that you have to press the return key to make it process any characters on most terminals (this does not happen if you make your program read from a file, for instance). So if you press y then it won't go out of the read call, until you hit the return key. However, then it will normally proceed and exit the loop.
As others mentioned you are better off with reading a whole line, and then decide what to do. You can also check the number with C++ streams instead of C functions:
bool checkForDouble(std::string const& s) {
std::istringstream ss(s);
double d;
return (ss >> d) && (ss >> std::ws).eof();
}
This reads any initial double number and then any remaining whitespace. If it then hit eof (end of the file/stream), it means the string contained only a double.
std::string line;
while(!getline(std::cin, line) || !checkForDouble(line))
std::cout << "Please enter a double instead" << std::endl;
For the char, you can just test for length 1
std::string line;
while(!getline(std::cin, line) || line.size() != 1)
std::cout << "Please enter a double instead" << std::endl;
If you want to read only 1 char and continue as soon as that char was typed, then you will have to use platform dependent functions (C++ won't provide them as standard functions). Look out for the conio.h file for windows for instance, which has the _getch function for this. On unix systems, ncurses provides such functionality.
cin >> _double will always get you a double, whether they typed in "42", "0" or "mary had a little lamb". You need to read the user input as a string, then test that string to see if it is a double. sscanf will return 0 if it can't convert the input string to the desired type:
cout << "Please enter a DOUBLE:\n" << endl;
string s;
cin >> s;
if( !sscanf(s.c_str(), "%lf", &_double) )
{
done = false;
cout << "Not a number, sparky. Try again." << endl;
continue;
}
Also, identifiers with leading underscores like you have are reserved by the language. Don't get in the habit of naming things like _double -- someday, they may not work.

Console is being flooded when error checking for things that are not an int

I'm trying to only allow integer values into my program, so I've made the following function. The function is similar to other ones I've seen online, and mine seems to work just fine up until I add an ! in front of it to check if something is not an int.
Function to check if input is an integer:
bool isInteger(std::string s)
{
for (int i = 0; i < s.length(); i++)
{
if (isdigit(s[i]) == false)
{
return false;
}
return true;
}
}
Function being put to use:
int getLevel()
{
int level;
std::cout << "Level One\n";
std::cout << "Level Two\n";
std::cout << "Level Three\n";
std::cout << "Level Four\n";
std::cout << "Level Five\n";
std::cout << "Enter your level (1-5): ";
std::cin >> level;
while (!isInteger(std::to_string(level)) || level < 1 || level > 5)
{
std::cout << "Enter an integer value between 1-5 inclusive: ";
std::cin >> level;
}
clrscr();
return level;;
}
I believe the function works just fine until I put the ! in front of it. I am trying to only allow integer input into my program, and when I enter a double or string, the console becomes flooded with the message "Enter an integer value between 1-5 inclusive: " and doesn't give any time to enter an input. I am fairly new to c++ programming and could use some advice. Thank you!
std::cin >> level;
will try to read an integer and it will never read anything other than an integer. If this fails std::cin's failbit is set and further input operations (like std::cin >> level; inside the loop) are skipped.
You need to check if the reading succeeded and ignore the current input if not. Like this for example:
std::cout << "Enter your level (1-5): ";
while(!(std::cin >> level) || level < 1 || level > 5) {
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Enter an integer value between 1-5 inclusive: ";
}
As little semi-related hint: level will always be an integer. Converting it to a string will always be the string-representation of an integer, so isInteger(std::to_string(level)) will always be true, unless level is negative, because you don't check for the sign.
Also that return true; in isInteger must be outside the loop, else you only check the first character.
Thanks to all the replies and clarification, I've managed to come up with a solution of my own.
New isInteger function that now checks for everything that is needed including inputs like "0004" that a user suggested above:
bool errorCheck(std::string s)
{
int intLevel;
std::stringstream tempLvl(s);
tempLvl >> intLevel;
for (int i = 0; i < s.length(); i++)
{
if (isdigit(s[i]) == false || s[0] == '0' || intLevel < 1 || intLevel > 5)
{
return false;
}
}
return true;
}
The method in action:
std::cout << "Enter your level (1-5): ";
std::cin >> stringLevel;
while (!errorCheck(stringLevel))
{
std::cout << "Enter an integer value between 1-5 inclusive: ";
std::cin >> stringLevel;
}
std::stringstream lvl(stringLevel);
lvl >> level;
clrscr();
return level;
}
Please let me know if you spot any problems with the code or have any easier solutions. Thanks for all the help!
ok i am gonna tell u the fact that console input extracts the input from console so if u ever tried to do something like that
i.e read string in place of integer the cin is going to be in bad state you can check this fact by putting an if like this
if(!cin>>level) break;
and u will find it working actually stream takes input from the console and convert it to boolean value so u can always check it's state bad state return false else true...... ..
SO,finally the bug is in cin>>level...
I hope u understood.... also check out that return true statement..
i am gonna put u reference link for more answer on this bug...
user enters String instead of Int

Recipe to nutrition converter

I have the whole thing ready to go, but I'm down to one problem, my professor wants us to ask the user to put in how many servings there will be, my problem is here:
string recipeName, userInputStr, servingNumber;
int userInputInt;
double totalCals, totalCarbs;
// initialize accumlator variables
totalCals = 0.;
totalCarbs = 0;
// asking for name of recipe and number of servings
cout << "What is the name of your recipe? ";
getline(cin, recipeName);
cout << "How many servings would you like? ";
getline(cin, servingNumber);
istringstream(servingNumber) >> totalCals, totalCarbs;
if (servingNumber<1 || servingNumber>10)
{
cout << "You have entered the wrong answer. " << endl;
return 0;
}
more specifically, it's here:
if (servingNumber<1 || servingNumber>10)
I keep getting an error on the < and > saying "no operator matches these operands"
I was told I'm supposed to convert the string servingNumber to int then compare it, but isn't it converted here?:
istringstream(servingNumber) >> totalCals, totalCarbs;
and then compared on the if statement?
I'm not sure what I'm doing wrong..
You declared those variables as strings, but when you compare them to integer, no overloads exists that take those arguments, and there is no acceptable conversion. I think you meant for them to be integers:
string recipeNamem userInputStr;
int servingNumber; /*
^^^
You also don't need the istringstream either.
Also, instead of getline(cin, servingNumber), do cin >> servingNumber.
You are defining servingNumber as a string in your code. You do not compare a string with numbers, the operator is not defined for the string class.
You're getting this error because you're trying to compare a string with a number in your if statement. Beyond that there are some other things with this code that might be worth looking at.
The first is the way you define variables. In C the idiom was to define all the variables at the top of your function as you're doing here. However in C++ we prefer to define variables where they are used. The goal is to reduce the amount of thinking you need to do on a chunk of code:
string recipeName;
cout << "What is the name of your recipe?";
getline(cin, recipeName);
string servingNumber;
double totalCals;
double totalCarbs;
getline(cin, servingNumber);
istringstream(servingNumber) >> totalCals, totalCarbs;
if( servingNumber < 1 || servingNumber > 10)
{
cout << "You have entered the wrong answer. " << endl;
}
The next issue is that istringstream(servingNumber) >> totalCals, totalCarbs; doesn't do what you think it does. I don't know how you're planning to use totalCals and totalCarbs but right now this line only sets totalCals and does nothing to totalCarbs.
Finally your major issue is that you're trying to compare servingNumber (a string) to a raw integer. We need to convert servingNumber to an integer. Some people have recommended atoi which will do the job but is often considered unidiomatic C++. Since you're already using stringstream we can use that to convert our number like so:
string recipeName;
cout << "What is the name of your recipe?";
getline(cin, recipeName);
string servingNumberInput;
double totalCals;
double totalCarbs;
getline(cin, servingNumberInput);
istringstream(servingNumberInput) >> totalCals, totalCarbs;
int servingNumber;
istringstream(servingNumberInput) >> servingNumber;
if( servingNumber < 1 || servingNumber > 10)
{
cout << "You have entered the wrong answer. " << endl;
}
Alternatively if you're not depending on getline you can just stream the number directly in from cin like so:
string recipeName;
cout << "What is the name of your recipe?";
getline(cin, recipeName);
int servingNumber;
cin >> servingNumber;
if( servingNumber < 1 || servingNumber > 10)
{
cout << "You have entered the wrong answer. " << endl;
}
I got rid of the totalCarbs and totalCals stuff because we don't have any idea what they're doing at the moment.

C++ cin only accept numeric values

I've written this piece of code that allows the user to choose input either the value 1 or 2. This is working perfectly fine aside from one minor issue:
If the user inputs something like "1asdaosd" the input is recognized only as 1.
I've tried using the isdigit function but I still didn't manage to make this work.
bool validInput;
do
{
cout << "Choose the game type: ";
cin >> gametype;
validInput = true;
if (cin.fail())
{
validInput = false;
cin.clear();
cin.ignore(std::numeric_limits<int>::max(), '\n');
}
if (gametype<1 || gametype>2) {
validInput = false;
}
} while (!validInput);
The expected behaviour should be:
Anything other than "1" or "2" shouldn't be considered a validInput and therefore repeating the cycle. What happens is that "1asdasd" or "2aods" is considered a validInput but I want it to fail.
Below is a method based on stuff I read in one of the early chapters of Stroustrup's Programming: Principles and Practice Using C++ and an answer provided by Duoas at cplusplus.com. It defines a function, get_int_between(), that allows you to do something like this:
int my_variable;
get_int_between(my_variable, min, max, prompt, error_msg);
Which would prompt, validate, and store into my_variable.
Just for fun, I've also included a function, get_int(my_variable, prompt, error_msg), that does the same thing but allows an integer of any value.
#include <iostream>
#include <sstream> // stringstream
void get_int(int& d, std::string prompt, std::string fail);
void get_int_between(int& d, int min, int max, std::string prompt, std::string fail);
int main()
{
int my_number = 1; // initialize my_number
get_int(my_number, "Please enter an integer: ", "Sorry, that's not an integer.\n");
//Do something, e.g.
std::cout << "You entered: " << my_number << "\n";
get_int_between(my_number, 1, 2, "Choose the game type (1 or 2): ", "Sorry, that's not an integer.\n");
//Do something, e.g.:
std::cout << "Let's play Game " << my_number << "!\n";
return 0;
}
void get_int(int& d, std::string prompt, std::string fail)
{
while(1) {
std::cout << prompt;
std::string str;
std::cin >> str;
std::istringstream ss(str);
int val1;
ss >> val1;
if(!ss.eof()) {
std::cout << fail;
continue;
} else {
d = val1;
break;
}
}
}
void get_int_between(int& d, int min, int max, std::string prompt, std::string fail)
{
while(1) {
get_int(d, prompt, fail);
if(d > max || d < min) {
std::cout << "Sorry, your choice is out of range.\n";
continue;
}
break;
}
}
If you want to use strings use getline.
#include <iostream> // std::cin, std::cout
int main ()
{
char name[256], title[256];
std::cout << "Please, enter your name: ";
std::cin.getline (name,256);
std::cout << "Please, enter your favourite movie: ";
std::cin.getline (title,256);
std::cout << name << "'s favourite movie is " << title;
return 0;
}
if you make gametype as an int it will only accept 1 or 2 (of course you have to prevent other numbers to be accepted).
It's because gametype is an integer, so it's trying to read as much as would be valid for an integer. 1asdaosd is not a valid integer so it stops at the 1. If you want to read that thing in completely you'll have to make gametype a string for example, but then you won't be able to compare it to integers as you already do.
You can read it as a string if you want, and if you want to handle the case of strings and ints both, then you can use something like stoi to attempt to convert the string to an integer. Then catch the std::invalid_argument exception so you can know if the string can be converted to an integer. If it can't, then you know to keep it as a string.
It reads an int as far the input can be construed as such. Then stops. If you read into a string variable it will get it all.
Read data into a string variable.
Check that data is a valid integer.
Convert string to integer.
Tedious but it's the only way to do it
I'm guessing you want one input value on each line. You need to read this as string and then check if you got more than you asked for. If you need it as an integer you can convert the read string later.
I'm also assuming you only need to read single digit integers. More digits need the string to integer conversion in the loop and some more checks.
string gametype;
do
{
cout << "Choose the game type: ";
// read one word as string, no conversion, so will not fail (may hit eof though)
cin >> gametype;
// ignore rest of line (assuming you want next valid input on next line)
cin.ignore(std::numeric_limits<int>::max(), '\n');
}
while ( gametype.size() != 1 || gametype.at(0) < '1' || gametype.at(0) > '2') );
// char to int conversion (single digit only)
int gametypeint = gametype.at(0) - '0';
// other way to convert string to int
istringstream iss(gametype);
iss >> gametypeint;
// yet another way (C++11)
gametypeint = stio(gametype);

What's wrong with the following C++ code involving input and string?

#include <iostream>
typedef int temperature;
temperature celsiustemperature[4];
int main()
{
using namespace std;
cout << "Enter a start temperature in celsius: ";
cin >> celsiustemperature[0];
cout << "Enter an end temperature in celsius: ";
cin >> celsiustemperature[1];
cout << "You printed " << celsiustemperature[0] << " and " << celsiustemperature[1] << "." << " Is this correct?" << endl;
char szYesOrNo;
cin >> szYesOrNo;
switch (szYesOrNo)
{
case "yes":
cout << "win";
break;
case "no":
cout << "winner";
break;
}
return 0;
}
I cannot figure out what is wrong with the following code. Sorry for not adding comments; I want it to print win if the user inputs yes and winner if user inputs no.
This won't compile, because szYesOrNo is a char, and you are comparing it with string literals in your switch statement. String literals are of type const char[], which cannot be directly compared to char.
Use std::string instead of a char:
std::string szYesOrNo;
This will also force you to remove the switch, because switch cannot operate on a string value (also notice, that your switch does not have a default case, so it won't handle incorrect input). Just do it this way:
if (szYesOrNo == "yes")
{
cout << "win";
}
else if (szYesOrNo == "no")
{
cout << "winner";
}
else
{
// Handle wrong input...
}
You can't switch on a string. Only on an integer-like type (ints, enums, chars, longs).
The main problem with your code is that you declare a variable as char szYesOrNo; which can only hold ONE symbol, such as a letter, but then expect the character to enter a whole word. You should use a string to do this instead. When you fix that, you will need to use if statements instead of a switch statement to make decisions.
First of all, szYesOrNo is a single char and so can only contain one character. When you do cin >> szYesOrNo;, you are only reading y or n.
Second, you're trying to use a switch statement to compare this single char to the string literals "yes" and "no". This comparison doesn't make sense. The string literals are of type "array of N const char".
Instead, use std::string like so:
string szYesOrNo;
cin >> szYesOrNo;
if (szYesOrNo == "yes") {
cout << "win";
} else if (szYesOrNo == "no") {
cout << "winner";
}
szYesOrNo is a character, so you cannot switch it in a case of "yes" which is a string ( 3 characters )
char szYesOrNo;
This is a single character.
switch (szYesOrNo)
{
case "yes":
This will compare the value of the single character with the address of the string "yes", which isn't what you want.
Either input to a string, or compare chars.
To compare chars:
switch (szYesOrNo)
{
case 'y':
To compare strings, you can't use a switch statement. You could use nested if/else:
string szYesOrNo;
if(szYesOrNo == "yes") {
cout << "win";
} else if(szYesOrNo == "no") {
cout << "winner";
}
You can use == when comparing a string to a char[] (which is what "yes" is). string makes sure the contents are compared rather than just the addresses.