Using successive cin >> input loops - c++

I have to loops to gather input, the first gathers input into a vector of doubles...
double input;
while (cin >> input)
{
list.push_back(input);
}
and the second gathers input into a vector of ints...
int input;
while (cin >> input)
{
list.push_back(input);
}
The second loop keeps auto-exiting and so I added the following two lines...
cin.clear();
cin.ignore(INT_MAX,'\n'); // I've also tried cin.ignore()
However this has occurred in my output being discarded in the second loop. How can I get both of these to work the way they need to?

The first loop reads until the stream goes bad because there isn't any double to read from. When the stream has gone bad it won't become good again unless you do something, e.g., using std::cin.clear() to clear the state flags.
Of course, just clearing the state flags won't make much of a difference because it would have read all viable numbers: the format of valid doubles is a superset of the format of valid ints (well, OK, unless they are using base 16). That is, you'll need some sort of separator, probably a non-space, non-digit character. Your use of ignore() should skip over a separator and up to the next newline (although the magic value isn't INT_MAX but std::numeric_limits<std::streamsize>::max()).
It is unclear what you are trying to input but if you use something like
1 2 3 exit 4 5 6
the first three values would be read as double and everything else would be ignored. That is, you may want to be ignore characters a bit more careful, e.g., clear the input and keep trying to read an int and clear() and ignore() until this is successful:
// skip separator:
std::cin.clear();
int input;
while (!(std::cin >> input)) {
std::cin.clear();
std::cin.ignore(); // ignore the next character only
}
do {
list.push_back(input);
} while (std::cin >> input);

Related

Safe operation to clear the empty input buffer in C++

I was looking at this post and few other. What happens if ignore() is called when input buffer is already empty? I observed in below code that if ignore() is called when buffer is already empty, it will not work and waits for some character to be entered first.
int main(void)
{
char myStr[50];
cin.ignore (std::numeric_limits<std::streamsize>::max(),'\n');
cout<<"Enter the String\n";
cin>>myStr;
// After reading remove unwanted characters from the buffer
// so that next read is not affected
cin.ignore (std::numeric_limits<std::streamsize>::max(),'\n');
}
cin.clear() after ignore() creates further problem if the buffer is already empty it looks. I guess clearing the buffer after cin() is safe. But what if I do not know the status of input buffer and I clear even when it is already empty? Do I have to check first if input buffer is empty using cin.fail() or something similar if any?
Secondly, cin itself may not be safe as space is not allowed. So getline() is suggested by some SO posts as given here. But does getline() also requires clearing input buffer or is it safe always? Does the code below work without any trouble (it works now, but now sure if it is safe code).
void getString(string& str)
{
do
{
cout<<"Enter the String: ";
getline(std::cin,str);
} while (str.empty());
}
Other SO references:
Ref 3
Breaking down main:
int main(void)
{
char myStr[50];
cin.ignore (std::numeric_limits<std::streamsize>::max(),'\n');
A bad idea, but you noticed that already. There must be a newline in the stream or you sit and wait for one. If the user's not expecting this behaviour you can expect to wait a long time and have a frustrated user. That's a bad scene.
cout<<"Enter the String\n";
cin>>myStr;
Also a bad idea, but for a different reason. >> doesn't know it should stop at 49 characters to prevent overflowing myStr. Bad things happen at that 50th character.
// After reading remove unwanted characters from the buffer
// so that next read is not affected
cin.ignore (std::numeric_limits<std::streamsize>::max(),'\n');
This one is safe. >> won't consume the newline, or any other whitespace and in order for the stream to hand over the data from the console someone must have hit enter and provided a newline.
}
A general rule of thumb is to not ignore unless you have reason to ignore, and if you have reason, ignore right away. Do not wait until before the next stream operation to ignore, be cause what if this operation is the first? Or the previous operation did not leave anything to ignore?. ignore after the operation that left what you want ignored in the stream. So
std::string getfirstword()
{
std::string firstword;
if (std::cin >> firstword)
{
cin.ignore (std::numeric_limits<std::streamsize>::max(),'\n');
return firstword;
}
return ""; // or perhaps
// throw std::runtime_error("There is no first word.");
// is more appropriate. Your call.
}
is good, but
std::string getfirstword()
{
cin.ignore (std::numeric_limits<std::streamsize>::max(),'\n');
std::string firstword;
if (std::cin >> firstword)
{
return firstword;
}
return "";
}
is an offence in the eyes of all that is holy. Don't do it.
As for getline, it gets a line. All of it up to the end of the file or the end of the line, whichever comes first. It also eats the end of the line for you so you don't have to worry about a stray newline harshing your mellow later.
If you only want part of the line, you will have to break it down. Typical usage for this is something along the lines of
std::string line;
if (std::getline(std::cin,line))
{
std::istringstream istr(line);
std::string firstword;
if (istr >> firstword)
{
// do something with firstword
}
else
{
// there is no firstword. Do something else.
}
}
getline reads everything up to and including the newline. It's no longer in the stream, so I'd consider this safe. You don't have to worry about garbage hanging around on the end of the line. You may have to worry about the next line, though.

Enter character instead int C++

I am writing a code that tally when an integer data type or character is entered.
int numero,
countInteger = 0;
countCharacter = 0;
while ( 1 ) {
try {
cin >> numero;
cout << numero;
throw numero;
} catch (...) {
countCharacter++;
cout << "Error";
}
}
If I entered Integer, counter in "countInteger" (but not show it in the code). If I enter a character, it is aa exception and recorded in "countCharacter".
But when I run the code generates an infinite loop and does not allow me to re-enter again. They could help me please. Guide me, you may have a bad concept.
When you try to read an integer, and you give something that's not an integer as input, there are two things happening: The first is that the stream gets its failbit set, the second things that happens is that the input is not extracted. So next iteration you read the same input again, and again and again...
I suggest another tactic: Read as a character, then see if it is a digit, an alphabetic character, or something else completely. Optionally, if you need the actual full number, read as a string, and try to convert to an integer.
A clarification: Input using std::cin is buffered. When you use the input operator >> then std::cin extracts characters from the buffer. If you try to read a number, but the first character in the buffer is not a digit, then the input operator will fail, and leave the character in the buffer.
Simple (hopefully) example:
Lets say you have this code
int number;
std::cin >> number;
std::cin >> number;
std::cin >> number;
As input for that part of the code, you enter
123abc
The first input will read 123 from the input, and stop at the letter, leaving the input as
abc
Now we come to the second input, and the code will see that the first character is not a digit, so it will set the failbit in the stream and leave the input as is:
abc
Then with the third input, the exact same thing as in the second happen.
Now imagine this was in a loop instead, the input operator >> will iteration after iteration see the non-digit input an promptly return, effectively giving you an infinite loop.
Now for a clarification of my suggestion... Depending on the goals and requirements of the program, you can instead read into a character and use the character classification functions to see what types you have.
Something like
int countDigit = 0;
int countCharacter = 0;
char ch;
while (std::cin >> ch)
{
if (std::isdigit(ch))
++countDigit;
else if (std::isalpha(ch))
++countCharacter;
else
{
// Not a digit or an alphabetic character
// I.e. newlines, spaces, control characters, etc.
}
}
Finally a note about using exceptions for this: Most people would consider it bad. Exceptions are for exceptions, exceptional cases, not as part of the normal flow of the program. Throwing an exception is expensive and disrupts the normal flow. Only use them for exceptional things, like errors.

What cin.ignore() does exactly?

I've been told by my professor that every time I use cin, I should always follow it with cin.ignore(100, '\n'). But, I never understood why?
Here is an example:
const int MAX = 200;
char input[MAX];
cout << "Enter something: ";
cin.get(input, MAX);
cin.ignore(100, '\n'); //why necessary?!!
You don't need to use ignore every time, but it is good to use after formatted input, or in cases like yours where you only read a specified amount.
In your example, if I were to type in over 200 characters, any future input might be in for a rough surprise.
char input[200];
std::cin.get(input, 200);
After this executes, the first 200 characters were extracted, but anything after that is still left lying in the stream. It also leaves the newline ('\n') character in it. Anytime you want to extract input after this, it'll read in the remaining characters from our previous input.
This happens with formatted input, too. Take this example:
int age;
std::string name;
std::cin >> age;
std::getline(std::cin, name);
What you want is to type in an age, like 32, and a name, like "Bob". What happens is you input the age, and the program skips reading the name. When std::cin uses >> to read into variables, it leaves the '\n' character that was put into the stream by hitting enter. Then, getline reads in that newline character and stops, because it hit a newline and thinks it is done.
ignore solves this problem by discarding everything up to and including the next newline character, so that the extra input doesn't mess with future reads.
std::cin.ignore(std::numeric_limits<std::streamsize>::max());
cin.ignore(100, '\n');
It ignores the first 100 characters, but if the function encounters '\n' before ignoring 100 characters, the function will stop discarding characters. So I assume that your professor wants you to ignore the rest of the data on the line unless it's longer than 100 characters.

stop inupt if input no double

first of all I'm sorry for my
bad english.
I'm trying to read some numbers and write them into a vector in C++.
This should go as long as the input is a double number and the
loop should be stopped if the user writes an 'a'.
My Question is how can I check if the input is 'a'.
Breaking the loop is not the problem
while(true){
if(!(cin>>userInput)){
//here i want to know if the input is 'a' or some other stuff//
//also i want to do some other stuff like printing everything//
//what already is in the vector//
//when everything is done; break//
}
else
//the input is a valid number and i push it into my vector//
'userInput' is defined as double so the loop will stop.
My Problem is, if the user write 'q' the loop stops but it's instantly stoping the whole program. My try look like this:
while(true){ //read as long as you can
cout<<"Input a number. With 'q' you can stop: "<<endl;
if(!(cin>>userInput)){ //here the progam stops when the input is anything but a number
cout<<"How many numbers do you want to add up?"<<endl; //there are numbers in a vector that should be added up
cin>>numberOfAdditions;
break;
}
So I have a vector with some numbers the users writes down (20,50,90,...)
When the input is equal to 'q' (in this example everything but numbers )
the loop stops and I want to ask the user how many numbers should be added.
The cout-command is displayed but the input is beeing skipped.
So my program is not reading how many valued from the vector I want to add.
I hope you know what I mean and I don't want to use two questions and two variables to save the input but if it's not working without it I'll change my program.
Have a nice Day :)
Because your Input variable is of type double you have to flush the Input from cin before reading again. Otherwise there is still a newline in the buffer.
Consider the following example:
#include <iostream>
using namespace std;
int main(){
double userInput;
int numberOfAdditions;
while(true){ //read as long as you can
cout<<"Input a number. With 'q' you can stop: "<<endl;
if(!(cin>>userInput)){ //here the progam stops when the input is anything but a number
cout<<"How many numbers do you want to add up?"<<endl; //there are numbers in a vector that should be added up
cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
cin.clear();
cin.ignore(INT_MAX,'\n');
cin >> numberOfAdditions;
break;
}
}
return 0;
}
The two Statements:
cin.clear();
cin.ignore(INT_MAX,'\n');
are flushing the Input stream until the newline is encountered.
The first answer already explains how to flush the cin stream after the user types in a char.
If you want to determine which character it was, you should define userInput as std::string. If the string is not "q" or "a" or whatever you are looking for, you have to cast the string to a double, just like this:
std::string str;
cin >> str;
if (str == "j")
// User typed in a special character
// ...some code...
else
double d = atof(str.c_str()); // Cast user input to double
Notice that the result of the cast is zero, if the user typed in any other string than the ones you especially look for.

c++: istringstream

I am creating a simple command parser using c++, and I am trying to use istream >> to check whether I am inputting a number or a character.
input:
a = 10
b = a
parser.cpp:
string inputLine, varLeft, equal, varRight;
double varValue
// please see update below
while(getline(cin, inputLine)){
istringstream stringSplitter(inputLine);
stringSplitter >> varLeft >> equal;
if(!(stringSplitter >> varValue)){
stringSplitter >> varRight;
}
}
The goal is, later in the code, if varRight is empty, I assume that the line of input was a double literal, otherwise, it's a string that denotes a variable. I understand there might be logical errors associated with mixed input starting with digits, but I am assuming that all input is correctly formatted for now. Why is the a in the second line of input discarded? What fix do you propose?
Update
The problem is not with the while loop statement, it is with the if statement at the end of the while code block.
In the actual code, the loop is not actually a while loop; I am using a vector object holding string commands, and iterating through them using a for loop which goes through the vector using iterators. But, in order to please the commenters, I have fixed it above.
If an input function fails, the stream will not allow any more extractions until you clear the failure state. You'll need to do that, after you've checked that the input to varValue failed, with std::basic_ios::clear:
if(!(stringSplitter >> varValue)){
stringSplitter.clear();
stringSplitter >> varRight;
}
I don't know how you're doing /* not end of input */ at the moment (hopefully you're not checking eof()!), but it's recommended that you do:
while (getline(cin, inputLine)) {
// ...
}
This checks that the line input was successful before diving into the loop.