i am trying to get a grip on built-in cin functions like cin.good() cin.fail() cin.ignore() cin.clear() etc. but there seems to be a problem with the following code, it works just fine but the line i have commented doesn't show on the runtime prompt. could someone point me to the right direction? :/
using namespace std;
void main()
{
int x = 0;
char y = 0;
int ch = 0;
do
{
cout << "Press 1 for int" << endl;
cout << "Press 2 for char" << endl;
cout << "Press 3 for exit" << endl;
cout << "enter choice = ";
cin >> ch;
if (ch == 1)
{
do
{
cout << "Enter an integer only = ";
cin >> x;
if (!cin.good())
{
cout << "Please enter integer only" << endl;
cin.clear();
cin.ignore(INT_MAX, '\n');
}
} while (cin.good() && x != 1);
}
else
if (ch == 2)
{
do
{
cout << "enter char only = ";
cin >> y;
if (cin.fail())
{ //the line below doesn't show up!
cout << "Please enter char only" << endl;
cin.clear();
cin.ignore(INT_MAX, '\n');
}
} while (!cin.fail() && y != 'e');
}
} while (ch != 3);
cout << "End of Program" << endl;
system("PAUSE"); // exit(1);
_getch();
}
cin.good()
Returns 0 if the stream has encountered problems such as reading the end of file, non-existent file. and 1 otherwise.
cin.bad()
Returns non-zero value if the stream is totally unusable, e.g. the file cannot be opened (but not if the stream has merely hit the end of the file).
cin.fail()
returns true if the last cin command failed, and false otherwise.
An example
int main() {
int i, j = 0;
while (1) {
i++;
cin >> j;
if (cin.fail()) return 0;
cout << "Integer " << i << ": " << j << endl;
}
}
Now suppose you have a text file - input.txt and it's contents are:
1 2 3 4 5 sahil 6 7
When you will run above short program on that, it will result like:
Integer 1: 1
Integer 2: 2
Integer 3: 3
Integer 4: 4
Integer 5: 5
it will not continue after 5th value as it quits after reading the sixth word, because that is not an integer: cin.fail() holds true.
cin.clear() and cin.ignore()
int age;
for (;;) {
cout << "Please enter your age: ";
if (cin >> age) {
break;
} else {
cout << "Please enter a valid integer age" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
Refer this for use in file handling:
bad()
Returns true if a reading or writing operation fails. For example, in
the case that we try to write to a file that is not open for writing
or if the device where we try to write has no space left.
fail()
Returns true in the same cases as bad(), but also in the case that a
format error happens, like when an alphabetical character is extracted
when we are trying to read an integer number.
eof()
Returns true if a file open for reading has reached the end.
good()
It is the most generic state flag: it returns false in the same cases
in which calling any of the previous functions would return true. Note
that good and bad are not exact opposites (good checks more state
flags at once).
The member function clear() can be used to reset the state flags.
Related
I need help debugging my code. So I made a program that adds and subtracts numbers but when I implemented a do-while loop to replay the program, the actual program closes and does not perform the do-while loop and does not replay the program. Is their something wrong with my code?
P.S. I am also using codeblocks IDE
#include <iostream>
using namespace std;
int main()
{
// Addition and Subtraction Calculator
int a_number, number1, number2, sum, number3, number4, subsum, again;
// subsum = subtracted sum
// number1 and number2 are variables that hold the users input for addition
// number3 and number4 are variables that hold the users input for subtraction
do
{
cout << "Addition & Subtraction Calculator" << endl;
cout << "-------------------------------------------" << endl;
cout << "1. Addition" << endl;
cout << "2. Subtraction" << endl;
cout << "Please enter a number [1 or 2]" << endl;
cin >> a_number;
while (a_number < 1 || a_number > 2)
{
cout << "Please enter either 1 or 2" << endl;
cin >> a_number;
}
switch (a_number)
{
case 1:
cout << "Please enter a number" << endl;
cin >> number1;
cout << "Please enter another number" << endl;
cin >> number2;
sum = (number1 + number2);
cout << "The sum is " << sum << endl;
break;
case 2:
cout << "Please enter a number" << endl;
cin >> number3;
cout << "Please enter another number" << endl;
cin >> number4;
subsum = (number3 - number4);
cout << "The answer to the subtraction problem is: " << subsum << endl;
break;
}
cout << "Do you want to try again? [y/n]" << endl;
cin >> again;
}
while (again == 'y' || again == 'n');
return 0;
}
OK. So the OP is using an int where they should have used a char. That covers the immediate problem. int again should be char again.
But there is an important point the other answers have missed.
int again;
cin >> again;
The user input will be converted into an integer as required by again. Inputting y or n fails to convert to an integer as neither y nor n are numbers and cannot be converted. again remains unchanged, keeping whatever junk value happened to be sitting at that spot in memory and might actually be a y or an n, but more importantly cin is now in an error state that needs to be cleared before continuing.
cin would have notified the OP of this if it had been tested. So let's test it.
int again;
if (cin >> again)
{
// got good input. Do something with it.
}
else
{
// got bad input.
cin.clear();
// that bad input is still in the buffer and needs to be removed
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// the above line will wipe out everything to the end of the stream or
// end of line, whichever comes first.
}
Why this is important: Because the OP is doing a lot of numeric input with cin and none of it is checked for validity. For example:
cout << "Please enter a number [1 or 2]" << endl;
cin >> a_number;
The program is broken completely and cannot exit without a kill signal if the user types in anything but a number.
Always check the error state and return codes. They are there to help. Always validate user input before using it. Users are evil and will try to break your program. Don't let them.
use char again; instead of int again;
in your code again is int and when in (again == 'y' || again == 'n')you compare again (an int) with a char, that does not make sense
You need to change the again variable to a char datatype because you need to store text. Something like this:
char again;
You also need to change the while statement to:
while(again != "n");
Or
while(again == "y");
This program should check if entered number is integer. It works fine with strings but not with doubles.
int test;
cout << "Enter the number:" << endl;
while(true) {
cin >> test;
if (!cin || test < 0) {
cout << "Wrong input, enter the number again:" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
test is int. istream >> operator is just dynamic casting to int and, then, you're losing decimal part.
Yo can just define test as float and cast it to int when needed.
Edit: Answering you last edit (I didn't refresh so I missed this part), what is happening is that, without the gotoyou're looping twice:
You enter 1.5
test is 1 and you don't enter if, so cin is not cleaned up.
loops again and cin immediately returns.
test is 0 so enters if statement and complains.
Hope this helps
Try this:
int test;
cout << "Enter the number:" << endl;
while ( true )
{
cin >> test;
if (!(test < 0 || !cin))
break;
}
cout << "Your chosen number is: " << test << endl;
Is that what you want?
In the below code, I'm running into an error when I try to get the user to input their name. My program just skips it over and goes right over to making the function calls without allowing the user to enter their name. Despite the error, my program is compiling. I'm not sure what's going wrong as I wrote that part based off other examples I found on here. Any suggestions?
#include <iostream>
#include <string>
#include <time.h>
using namespace std;
char showMenu();
void getLottoPicks(int[]);
void genWinNums(int[]);
bool noDuplicates(int[]);
const int SIZE = 7;
int main()
{
int userTicket[SIZE] = {0};
int winningNums[SIZE] = {0};
char choice;
string name;
srand(time(NULL));
do
{
choice = showMenu();
if (choice == '1')
{
cout << "Please enter your name: " << endl;
getline(cin, name);
getLottoPicks(userTicket);
genWinNums(winningNums);
for (int i = 0; i < SIZE; i++)
cout << winningNums[i];
}
} while (choice != 'Q' && choice != 'q');
system("PAUSE");
return 0;
}
Added the code for showMenu:
char showMenu()
{
char choice;
cout << "LITTLETON CITY LOTTO MODEL:" << endl;
cout << "---------------------------" << endl;
cout << "1) Play Lotto" << endl;
cout << "Q) Quit Program" << endl;
cout << "Please make a selection: " << endl;
cin >> choice;
return choice;
}
And getLottoPicks (this part is very wrong and I'm still working on it):
void getLottoPicks(int numbers[])
{
cout << "Please enter your 7 lotto number picks between 1 and 40: " << endl;
for (int i = 0; i < SIZE; i++)
{
cout << "Selection #" << i + 1 << endl;
cin >> numbers[i];
if (numbers[i] < 1 || numbers[i] > 40)
{
cout << "Please choose a number between 1 and 40: " << endl;
cin >> numbers[i];
}
if (noDuplicates(numbers) == false)
{
do
{
cout << "You already picked this number. Please enter a different number: " << endl;
cin >> numbers[i];
noDuplicates(numbers);
} while (noDuplicates(numbers) == false);
}
}
}
After doing cin >> choice; inside char showMenu(), if a user inputs 1[ENTER], the char consumes 1 character from cin, and the newline stays inside the stream. Then, when the program gets to getline(cin, name);, it notices that there's still something inside cin, and reads it. It's a newline character, so getline gets it and returns. That's why the program is behaving the way it is.
In order to fix it - add cin.ignore(); inside char showMenu(), right after you read the input. cin.ignore() ignores the next character - in our case, the newline char.
And a word of advice - try not to mix getline with operator >>. They work in a slightly different way, and can get you into trouble! Or, at least remember to always ignore() after you get anything from std::cin. It may save you a lot of work.
This fixes the code:
char showMenu()
{
char choice;
cout << "LITTLETON CITY LOTTO MODEL:" << endl;
cout << "---------------------------" << endl;
cout << "1) Play Lotto" << endl;
cout << "Q) Quit Program" << endl;
cout << "Please make a selection: " << endl;
cin >> choice;
cin.ignore();
return choice;
}
from looking at code showMenu function has problem. and it's not returning asccii equivalent of '1' that is: 31 integer. try printing value returned by showmenu. you will get that
UPDATE:
It is because cin in delimited by ' '(whitespace) and getline by '\n' character, so when enter name and press enter cin in showmenu will consume whole string except '\n' from istream and that is read by getline. to see this when it ask for choice enter string like 1 myname (1 whitespace myname)and press ENTER will display name. now cin will read 1 in choice and myname in name by getline.
New to C++. Having issues correctly looping while handling errors. I am trying to check if user input is an integer, and is positive.
do{
cout << "Please enter an integer.";
cin >> n;
if (cin.good())
{
if (n < 0) {cout << "Negative.";}
else {cout << "Positive.";}
}
else
{
cout << "Not an integer.";
cin.clear();
cin.ignore();
}
}while (!cin.good() || n < 0);
cout << "\ndone.";
When a non-integer is entered, the loop breaks. I feel like I am misunderstanding the inherent usage of cin.clear() and cin.ignore() and the status of cin during this loop. If I remove the cin.ignore(), the loop becomes infinite. Why is this? What can I do to make this into an elegantly functioning loop? Thank you.
In your non-integer branch you are invoking further cin methods so cin.good() gets reset to true.
You could change your code to something like this:
while(1) { // <<< loop "forever"
cout << "Please enter an integer.";
cin >> n;
if (cin.good())
{
if (n < 0) {cout << "Negative.";}
else { cout << "Positive."; break; }
} // ^^^^^ break out of loop only if valid +ve integer
else
{
cout << "Not an integer.";
cin.clear();
cin.ignore(INT_MAX, '\n'); // NB: preferred method for flushing cin
}
}
cout << "\ndone.";
or you can simplify it even further like this:
while (!(cin >> n) || n < 0) // <<< note use of "short circuit" logical operation here
{
cout << "Bad input - try again: ";
cin.clear();
cin.ignore(INT_MAX, '\n'); // NB: preferred method for flushing cin
}
cout << "\ndone.";
int n;
while (!(cin >> n)||n<0)//as long as the number entered is not an int or negative, keep checking
{
cout << "Wrong input. Please, try again: ";
cin.clear();//clear input buffer
}
//only gets executed when you've broken out of the while loop, so n must be an int
cout << "Positive.";
cout << "\ndone.";//finished!
Should do what you want.
Consider the following code which takes an integer input and then prints the cin stream state:
#include <iostream>
using namespace std;
int main()
{
int number;
cout<<"Enter a number \n";
cin>>number;
cout<<cin.rdstate()<<endl;
return 0;
}
If the number entered is "zzzz" then the rdstate returns a value of 4.
If the number entered is "10zzzz" then the rdstate returns a value of 0, number has a value of 10, and the input stream has "zzzz" in it.
My question is:
1. Why isn't a input of "10zzzz" treated as an invalid input (atleast one of the failure bits should have been set.)
2. What is an elegant solution to detect and handle this situation.
Thanks!!!
First of all I would like to ask what you are trying to do with:
cout<<cin.rdstate()<<endl;
Read this page for the proper use of rdstate()
http://www.cplusplus.com/reference/iostream/ios/rdstate/
second:
to check wetether the input is either stringtype or integer type you might want to add something extra wich will convert the input string to integer data and will respond with an error message when feeded an invalid input.
therefor this will help you out:
int main() {
string input = "";
// How to get a string/sentence with spaces
cout << "Please enter a valid sentence (with spaces):\n>";
getline(cin, input);
cout << "You entered: " << input << endl << endl;
// How to get a number.
int myNumber = 0;
while (true) {
cout << "Please enter a valid number: ";
getline(cin, input);
// This code converts from string to number safely.
stringstream myStream(input);
if (myStream >> myNumber)
break;
cout << "Invalid number, please try again" << endl;
}
cout << "You entered: " << myNumber << endl << endl;
// How to get a single char.
char myChar = {0};
while (true) {
cout << "Please enter 1 char: ";
getline(cin, input);
if (input.length() == 1) {
myChar = input[0];
break;
}
cout << "Invalid character, please try again" << endl;
}
cout << "You entered: " << myChar << endl << endl;
cout << "All done. And without using the >> operator" << endl;
return 0;
}