Undefined behaviour when entering `char` for integer variable with `std::cin` - c++

I have this while loop, just to check if the entered number is 2. If the user entered by accident a letter instead of a number the loop goes to infinity even though I've added isdigit, but didn't fix the loop from going crazy if the input is a character. This is code:
int num1;
bool cond {false};
while(!cond){
cout<<"enter 2:";
cin>>num1;
if (!isdigit(num1)){
cout<<"not a digit:";
cin>>num1;
}
//
if(num1 == 2)
cond = true;
}

I would suggest trying something a little more straightforward instead of your current code:
#include <iostream>
#include <limits>
using namespace std;
int main()
{
int num1;
cout << "Please enter the number 2:";
cin >> num1;
while (num1 != 2)
{
cin.clear(); //Clears the error flag on cin.
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "You did not enter the number 2, Please try again:";
cin >> num1;
}
return 0;
}
Now, cin.ignore(numeric_limits<streamsize>::max(), '\n'); is when it ignores up until '\n' or EOF \n is the delimiter meaning that, that is the character at which cin will stop ignoring.
Furthermore, numeric_limits<streamsize>::max() is basically saying there is no limit to the number of characters to ignore.
You need to use the header file #include<limits> to use this.

I recommend separating the reading of input data from converting it to a number. A good method for this is to use stringstream. Here's a working example:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
int num1;
string input;
bool cond{ false };
cout << "enter 2:";
while (!cond) {
getline(cin, input);
stringstream ss(input);
ss >> num1;
if( ss.fail() ){
cout << "not a digit:";
continue;
}
//
if (num1 == 2)
cond = true;
else
cout << "enter 2:";
}
return 0;
}

int num1;
bool cond {false};
do{
cout<<"enter 2:";
cin>>num1;
if (cin.good()) {
cond = true;
}else {
cin.clear();
cin.ignore();
cout << "Invalid, please enter 2." << endl;
}
}while(!cond);
While false, execute statements. Also, if you want the user to re-enter a number, cin must be flushed.

Try declaring the variable num1 as char because isdigit(ch) works for char and not for int.
I hope this solves your problem

Why does the loop iterate infinitely?
Let's take this example
int a;
std::cin >> a;
std::cout << "Entered: " << a;
Now let's test it with different inputs
with int
5
Entered: 5
10
Entered: 10
Yes just as we would expect, but what happens when you enter a char?
with char
r
Entered: 0
f
Entered: 0
Why does this happen?
When you declare the variable int, and then do std::cin >> , you are telling the input method that the user will enter an integer, but when it doesn't get what it expected, it will fail. C++ will not implicitly convert the value of char into int. Hence, you get strange results.
How to solve this?
As I have mentioned earlier, it fails. When this fails you can catch it this way
if (!(std::cin >> a))
{
std::cout << "Invalid input ! \n";
}
We're saying, if the input fails, show the message.
let's test this new code.
int a;
if (!(std::cin >> a))
{
std::cout << "Invalid input !\n";
}
else
{
std::cout << "Entered: " << a;
}
5
Entered: 5
r
Invalid input !
How to print char value of the int?
If you want to just print the ASCII value of the entered number, you need to cast the value into char.
You can do
int num = 48;
char character_value = num;
Here C++ will implicitly convert char into int.
But if you need a safer type of conversion, prefer using static_cast<>.
The syntax looks like this
int a = 5;
char character_value = static_cast<char>(a);
Static cast in C++
Type casting in C++
Dealing with invalid input in C++

Related

How to print out a double value without losing first digit

When I run my code, it only prints the decimal parts of the double. On another page, I took a inputted double and printed out the double the way it was inputted.
But for my following code, it only prints out the decimals. For example, when I input 1.95 it only prints out 0.95. Why is it removing the first digit? I see nothing in my code that points to this.
I have already tried it in a more simple way and it worked. And I dont see any problems that would mess with the double in my code.
#include <iostream>
using namespace std;
int main()
{
double price;
char user_input;
do
{
cout << "Enter the purchase price (xx.xx) or `q' to quit: ";
cin >> user_input;
if (user_input == 'q')
{
return 0;
}
else
{
cin >> price;
int multiple = price * 100;
if (multiple % 5 == 0)
{
break;
}
else
{
cout << "Illegal price: Must be a non-negative multiple of 5 cents.\n" << endl;
}
}
} while (user_input != 'q');
cout << price << endl;
}
When I input 1.95, I get 0.95. But the output should be 1.95.
Problem covered in other answer: Reading for the 'q' removed the first character from the stream before it could be parsed into a double.
A solution: Read the double first. If the read fails, check to see if the input is a 'q'.
#include <iostream>
#include <limits>
using namespace std;
int main()
{
double price;
while (true)
{
cout << "Enter the purchase price (xx.xx) or `q' to quit: ";
if (cin >> price)
{
// use price
}
else // reading price failed. Find out why.
{
if (!cin.eof()) // didn't hit the end of the stream
{
// clear fail flag
cin.clear();
char user_input;
if (cin >> user_input && user_input == 'q') // test for q
{
break; // note: Not return. Cannot print price if the
// program returns
}
// Not a q or not readable. clean up whatever crap is still
// in the stream
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
else
{
// someone closed the stream. Not much you can do here but exit
cerr << "Stream closed or broken. Cannot continue.";
return -1;
}
}
}
cout << price << endl;// Undefined behaviour if price was never set.
}
Another reasonable alternative is to read all input as std::string. If the string is not "q", attempt to convert it to a double with std::stod or an std::istringstream.
When you type 1.95 in the command line, variable user_input gets assigned '1', and price gets assigned .95.

Looping if user input invalid

I want to create a program that when a user inputs something that I didn't define, the program prompts him again.
I did it with if statements but it only loops for 1 time and doesn't do it again. I tried loops but whenever the input is false it just breaks the condition and refuses all inputs alike. In c++.
Any help is much appreciated.
#include <iostream>
#include <string>
using namespace std;
void xD(){string x;
do{cout << "Retry\n";
cin >> x;}while(true);}
//declaring a function to make the shop
void shop(){
string x;
float coins = 500;
float bow_cost = 200;
cout << "welcome to the shop\n";
cout << "Bow(bow)costs 150 coins.\n";
cin >> x;
// if u chose bow you get this and get to choose again
if (x == "bow"){
cout << "you bought the bow.\n you now have " <<coins - bow_cost << " coins." << endl; cin >> x;}
/*now the problem that whenever I excute the code and type something other than bow it gives me the cin only once more and then fails even if I type bow in the 2nd attempt*/
//in my desperate 5k attempt, I tried creating a function for it.. no use.
//i want it o keep prompting me for input till i type "bow" and the other block excutes. but it never happens.
else{xD();}
}
int main(){
string name;
string i;
cout << "if you wish to visit the shop type \"shop\"\n";
cin >> i;
if(i == "shop"){shop();}
else{cin >> i;}
return 0;
}
The problem lies on the condition in this loop block
void xD(){
string x;
do{
cout << "Retry\n";
cin >> x;
}while(true);
}
The while(true) condition makes it loops forever regardless of the input. To fix this, you can change the condition:
void xD(){
string x;
do{
cout << "Retry\n";
cin >> x;
}while(x!="bow");
cout << "you bought the bow. and some other messages"<<endl;
}
That should work. However, it is still too complicated for me. This can be simplified into the snippet below:
void shop(){
string x;
float coins = 500;
float bow_cost = 200;
cout << "welcome to the shop\n";
cout << "Bow(bow)costs 150 coins.\n";
cin >> x;
while (x!="bow"){
cout << "Retry\n";
cin>>x;
}
cout << "you bought the bow.\n you now have " <<coins - bow_cost << " coins." << endl; cin >> x;
}
Instead of doing this approach (which is checking the condition only once):
if (x == "bow"){
cout << "you bought the bow.\n you now have " <<coins - bow_cost << "
coins." << endl; cin >> x;
} else{
xD();
}
which is actually a RECURSIVE invocation to the method xD()
you should do a do-while loop,
example:
while (x.compare("bow") != 0)
{
cout << "sorry, wrong input, try again...";
cin >> x;
}
note the use of the compare method instead of the == operator
here more about it in the documentation
You can use return value of cin >> [your input object] here to check status or istream's method fail(). As soon as input stream fails to parse whole or part of streams it fails and stay in state of failure until you clear it. Unparsed input is preserved (so you can try to parse it differently?)m so if you try to >> again to object of same type, you'll get same failure. To ignore N chars of imput, there is method
istream::ignore(streamsize amount, int delim = EOF)
Example:
int getInt()
{
while (1) // Loop until user enters a valid input
{
std::cout << "Enter an int value: ";
long long x; // if we'll use char, cin would assume it is character
// other integral types are fine
std::cin >> x;
// if (! (std::cin >> x))
if (std::cin.fail()) // has a previous extraction failed?
{
// yep, so let's handle the failure, or next >> will try parse same input
std::cout << "Invalid input from user.\n";
std::cin.clear(); // put us back in 'normal' operation mode
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n'); // and remove the bad input
}
// Thechnically you may do only the above part, but then you can't distingusih invalid format from out of range
else if(( x > std::numeric_limits<int>::max()) ||
( x < std::numeric_limits<int>::min()))
{
std::cout << "Invalid value.\n";
}
else // nope, so return our good x
return x;
}
}
For strings parsing is almost always successful but you'll need some mechanism of comparison of string you have and one that is allowed. Try look for use of std::find() and some container that would contain allowed options, e.g. in form of pair<int,string>, and use int index in switch() statement (or use find_if and switch() within the function you give to it).
Consider that if() statement is a one_direction road, it checks the condition and if the condition was satisfied it goes to its bracket and do blah blah blah , if there is any problem with condition compiler passes ifand jump to compile other codes.
Every time that you begin to compile the codes it begins from int main() function. You did the wrong thing in the if and else statements again
Here is the correct code .I did the necessary changes.
#include "stdafx.h"
#include <iostream>
#include <string>
using std::string;
using std::cin;
using std::cout;
#define coins 500 ;
#define bow_cost 200 ;
int shop(string x)
{
//There is no need to allocate extra memory for 500 and 200 while they are constant.``
cout << "welcome to the shop\n";
cout << "Bow(bow)costs 150 coins.\n";
do
{
cout << "Input another :\n";
cin >> x;
if (x == "bow")
{
return (coins - bow_cost); //return to function as integer
}
} while (true);
}
int main()
{
string name, i;
cout << "if you wish to visit the shop type \"shop\"\n";
cin >> i;
if (i == "shop")
{
cout << "Input :\n";
cin >> name;
cout << shop(name) << "you bought the bow.\n you now have " << " coins." << "\n";
}
//argument passed to shop funnction parameters.
system("pause");
return 0;
}

Read Integer from User

I am trying to read an integer from terminal. Here's my code:
int readNumber()
{
int x;
std::cin >> x;
while(std::cin.fail())
{
std::cin.clear();
std::cin.ignore();
std::cout << "Bad entry. Enter a NUMBER: ";
std::cin >> x;
}
return x;
}
Whenever I run this code I get:
Type in the number for the newsgroup that shall be deleted:
joöä
Bad entry. Enter a NUMBER: Bad entry. Enter a NUMBER: Bad entry. Enter a NUMBER: Bad entry. Enter a NUMBER: Bad entry. Enter a NUMBER: Bad entry. Enter a NUMBER: 8
Why does it write "bad entry" multiple times?
If I remove std::cin.clear(); or std::cin.ignore();, the program just keeps writing
Enter a NUMBER: Bad entry. Can anyone explain why it does that?
This is actually a partial duplicate of an old question, but it is phrased differently enough that I will address it briefly here.
You get infinite printing without those two lines, because cin.clear() is required to clear the error flag that cin.fail() is reading. See the linked question for details.
Why does it still print more than once when those lines are there? When you do std::cin >> x;, your code will read the first character in your input, and attempt to parse it as an int. It will fail, and then in the next iteration of the loop, it will attempt to parse the next character and fail again. For each failure (that is, each character in your input), it will print Bad entry. Enter a NUMBER:. If you type some bad input with fewer characters, you will see what I mean.
There are multiple ways to fix this problem, but one simple fix is to read the entire input into a string, and try to parse it, instead of using cin directly into an int. Here is some sample code which needs to be compiled with one of the various compiler-dependent flags for C++11. I have tested it with your input and it appears to achieve the effect you desire.
#include <iostream>
#include <string>
#include <stdexcept>
bool tryParse(std::string& input, int& output) {
try{
output = std::stoi(input);
} catch (std::invalid_argument) {
return false;
}
return true;
}
int main(){
std::string input;
int x;
getline(std::cin, input);
while (!tryParse(input, x))
{
std::cout << "Bad entry. Enter a NUMBER: ";
getline(std::cin, input);
}
return x;
}
Try this anyway... As I type this directly into stackoverflow might have compilation error
int readNumber()
{
int x=0;
while(true)
{
std::cin >> x;
if(!std::cin.fail()){
break;
}
else{
std::cout << "Bad entry. Enter a NUMBER: " << std::endl;
std::cin.clear();
std::cin.ignore( std::numeric_limits<streamsize>::max(), '\n' );
}
}
}
int main() {
char* input;
std::cin >> input;
int x = std::atoi(input);
while(x == 0 && strcmp(input, "0") != 0) {
std::cout << "Bad entry. Enter a NUMBER: ";
std::cin >> input;
x = std::atoi(input);
}
return x;
}
Notice that when you have 3 non-int chars, it will repeat 3 times, when you have 5, it's repeated 5 times.
It's because cin is tries the first char, fails, try the second char, fails and so on until all your input chars are parsed.
cin.fail() returns true if the last cin command failed, and false otherwise.
Try this instead:
while(1)
{
std::cin >> x;
if (!std::cin.fail()) break;
std::cin.clear();
std::cin.ignore(10000,'\n');
std::cout << "Bad entry. Enter a NUMBER: ";
}

While keeps repeating on letters but not on #'s

I have a while loop here that only takes in 1 and 2 as the number, if i insert and number that is not these my else statement will keep asking for the correct one, which works correctly. But if i insert a letter my else statement loops forever. How can i fix this?
#include <iostream>
using namespace std;
int main()
{
int myChoice;
cin >> myChoice;
while ( myChoice >= 2 || myChoice <= 1)
{
if (myChoice == 1)
{
cout <<"food1";
break;
}
else if (myChoice == 2)
{
cout <<"food2";
break;
}
else
{
cout << " " << endl;
cout << "Please select the proper choices" << endl;
cout << "Try again: ";
cin >> myChoice;
}
}
return 0;
}
If you enter a non-number, then cin >> myChoice fails. That means that it leaves the input intact in the input buffer and when you get there again it tries to parse it and fails, and so on... You must clear the error state and ignore the non-digits. The simplest way is something like this:
cout << "Try again: ";
cin.clear(); // clear error state
cin.ignore(std::numeric_limits<streamsize>::max(), '\n'); // ignore till the end of line
cin >> myChoice;
The problem here is that the cin >> operator expects to receive an int input and receives a char input.
The istream module, of which cin is an instance, is using buffered I/O. This means that the user input is first stored in a buffer, and then read from that buffer when the user program accesses the >> operator. Ordinarily, if the >> operator succeeds in reading and parsing the user input, the read data is extracted from the buffer and the next invocation of the >> operator would continue where the last call left off. In you case, however, the >> operator attempts to parse the user input as a number and fails since it contains illegal chars which are not digits. The >> operator doesn't extract the read data from the buffer in this case and this same data is being referred to over and over again in the following calls to the >> operator.
You should empty the buffer on failure, the way ybungalobill suggested, for instance.
Your while condition is always true, then you use break to exit the loop. You could simplify things a bit like this:
#include <iostream>
using namespace std;
int main()
{
int myChoice;
cin >> myChoice;
while( myChoice != 1 || myChoice != 2 ) {
cout << endl;
cout << "Please select the proper choices" << endl;
cout << "Try again: ";
cin.clear();
cin.ignore(std::numeric_limits<streamsize>::max(), '\n');
cin >> myChoice;
}
// At this point myChoice is 1 or 2
if (myChoice == 1)
cout << "food1";
else if (myChoice == 2)
cout << "food2";
}

How do I make a C++ program that filter out non-integers?

Something like this
cout << "Enter the number of columns: " ;
cin >> input ;
while( input != int ){
cout << endl <<"Column size must be an integer"<< endl << endl;
cout << "Enter the number of columns: " ;
cin >> input ;
}
cin will do this for you, kind of. cin will fail if it receives something that is not of the same type as input. What you can do is this:
int input;
while(!(cin >> input))
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << endl <<"Column size must be an integer"<< endl << endl;
cout << "Enter the number of columns: " ;
}
The cin.clear() clears the error bits, and cin.ignore() clears the input stream. I'm using number_limits to get the maximum size of the stream, that requires that you #include<limits>. Alternatively you can just use a big number or a loop.
You can't do it like that; input has to have some concrete type.
The simplest approach that will work is to read a string from cin, then convert it to an integer in a second step with strtol or one of its relatives, and issue an error message if strtol doesn't consume the whole string.
#include<iostream.h>
using namespace std;
int main()
{
int x;
int input;
while(!0){
cout<<"Enter your option :";
cout<<"1 .Enter Column size :"<<endl;
cout<<"2.Exit "<<endl;
cin>>x;
switch(x)
{
case 1: cout << "Enter the number of columns: "<<endl ;
cin>>input;
if(input>0)
cout << "The number of columns: is "<<input<<endl ;
else
cout << "Enter the number of columns as integer "<<endl ;
case 2:exit(0);
}
};
return 0;
}
Many of the answers here use the cin's built in filter. While these work to prevent a char or string from being entered, they do not prevent a float entry. When a float is entered, it is accepted and the decimal value remains in the buffer. This creates problems with later requests to cin. The following code will check the cin error flag and also prevent float inputs.
*note: The cin.ignore statement may require some tweaking to fully bullet proof the code.
void main()
{
int myint;
cout<<"Enter an integer: ";
intInput(myint);
}
void intInput(int &x)
{
bool valid = true; //flag used to exit loop
do
{
cin>>x;
//This 'if' looks for either of the following conditions:
//cin.fail() returned 'true' because a char was entered.
//or
//cin.get()!='\n' indicating a float was entered.
if(cin.fail() || cin.get()!='\n')
{
cout<<"Error. The value you entered was not an integer."<<endl;
cout<<"Please enter an integer: ";
cin.clear(); //clears cin.fail flag
cin.ignore(256,'\n'); //clears cin buffer
valid = false; //sets flag to repeat loop
}
else valid = true; //sets flag to exit loop
}while(valid == false);
}
This is a very basic solution to your problem that newer programers should find useful for people trying to break their programs. Eventually there are more advanced and efficient ways to do this.
int input;
int count = 1;
while(count == 1){ //this is just a simple looping design
cin >> input;
if(cin.fail()){ //If the input is about to crash your precious program
cin.clear(); //Removes the error message from internal 'fail safe'
cin.ignore(std::numeric_limits<int>::max(), '\n'); //Removes the bad values creating the error in the first place
count = 1; //If there is an error then it refreshes the input function
}
else{
count--; //If there is no error, then your program can continue as normal
}
}
Here is the advanced code: stackoverflow.com/questions/2256527/