I read that cin terminates as soon as it sees a newline character or white space and it doesn't consume that and leaves it in the input buffer.
Therefore, between cin and cin.getline() commands, we should add a cin.get() to consume the endline character.
But if this is the case, how does two cin commands work?
For eg:
int N;
int M;
cin>>N;
cin>>M;
Once we take the input of N and press enter, then a newline character must be left in the input stream. When we reach to line cin>>M, how does it work given that cin should terminate as the character in the input stream now is "\n".
Please help me resolve my confusion. I'd be glad to know how the input and output in C++ works.
If you enter 1 5 at the prompt for N, N will be assigned 1 and M will be assigned 5. The spacees in between just get ignored by both. If you enter 15 then N will be assigned 15 and there will be a blinking cursor waiting for input for M
Related
Hey guys beginner in C++ and coding in general. I am currently making a tictactoe program. For the part of the program I am validating user input. Since it is a 3x3 table, I want to make sure their input is an integer and that they choose a number between 1~9.
To do this I wrote
//Validating user input
void move() {
std::cout << "It's Player" << player << "'s turn!\n";
while(!(std::cin >> position)){
std::cout << "Please choose a NUMBER between 1~9!\n";
std::cin.clear();
std::cin.ignore();
}
while(position < 1 || position > 9){
std::cout << "Please choose a number BETWEEN 1~9!\n";
std::cin.clear();
std::cin.ignore();
}
while(board[position - 1] != " ") {
std::cout << "Already filled please choose another number between 1~9!\n";
std::cin >> position;
}
}
It works but for some reason when I put in an input like 10, it would print Please choose a number BETWEEN 1~9! twice (for each digit) and if I input in for example "apple" it would print Please choose a NUMBER between 1~9! four times (for each character). How do i make it just print out the statement once?
Thank you!
Let me try to explain to you the problem. It is a little bit subtle and not that easy to understand. Both other answers adress only the obvious part.
Then, let us first recap that:
The boolean condition in the while statement is loop invariant. Meaning, it will not be modified within the loop. Whatever it was before the loop, will be the same after the loop body has been executed. The condition will never change.
So, for the case where you enter a wrong number:
If the input number is correct (1..9) and the while statement starts to evaluate the boolean expression, it will be false in this case and the loop will not be entered.
If the number is out of your selected bounds (<1 or >9), then the boolean condition is true. The while loop starts, but the condition relevant variable will not be changed in the loop boody and hence, the boolean expression is always true. The loop will run forever.
Additionally, and now comes the answer to your first question, the following will happen:
The text "Please choose a number BETWEEN 1~9!\n" will be shown (first time)
clear will be called for std::cin. The failbit was not set, but anyway. This does not harm
The ignore function is an unformatted input function. It will actively read the next character from the input buffer, which is the end of line `'\n' character.
We enter again the while statement. The condition is still true (position was not modified in the loop body), and we enter the loop again.
The text "Please choose a number BETWEEN 1~9!\n" will be shown (second time)
clear will be called for std::cin. The failbit was not set, but anyway. This does not harm
The ignore function is a formatted input function. It will actively read the next character from the input buffer. But there is none. So it will wait until a key is pressed. For example "enter". After that, it would go back to number 5.
By the way. If you would now enter "abc" then you would see the text 4 times for a,b,c and enter.
So, please remember: ignore is an input function!
Next. It is important to understand, that if you enter an unexpected value, like "apple" instead of "3", the formatted input function >> can do no conversion and sets the failbit. It will also not extract further wrong characters from the input stream (std::cinis a buffered stream). The characters that could not be converted are still in the buffer and wil be read next time.
Please read here about formatted/unformatted input. And especially read about the extraction operatpr >> here..
There you can read the following:
If extraction fails (e.g. if a letter was entered where a digit is expected), zero is written to value and failbit is set.
OK, understood. Then, what is going on here, if you enter "abc". Basically, the same as above.
Enter abc
The boolean condition !(std::cin >> position)will be evaluated to true, because an 'a' was read and cannot be converted to a number.
The std::cin's failbit will be set. The variable positionwill be set to 0.
"Please choose a NUMBER between 1~9!\n" will be shown
The failbit will be reset
Ignore will extract exactly the one wrong character and discard it
std::cin >> position`` will be called again and extract the next wrong character 'b'. 3., 4., 5., 6. will be done again. Until the last charcter in the buffer, the newline '\n' will be extracted. Then you may enter the next number.
The fix for that problem is simple:
ignore has a parameter, where you can specify, how many characters shall be ignored. So, not only one, but all until the end of line.
You should write:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
This will ignore all bad input.
And to fix your whole program, you could write at the top:
while (!(std::cin >> position) or (position < 1 ) or ( position > 9)) {
std::cout << "Please choose a NUMBER between 1~9!\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
while(position < 1 || position > 9){
This while loop will continue running as long as position is less than 1 or greater than 9, that's what this says.
But there's nothing in the while loop itself that changes the value of position. For that simple reason, if position's value at this point is outside of the range of 1-9, this while loop will execute forever.
You always need to keep in mind The Golden Rule Of Computer Programming: your computer always does exactly what you tell it to do instead of what you want it to do. Here, you told your computer to execute this while loop as long as position is less than 1 or greater than 9, so this is what your computer will do until this is no longer the case.
You can change your code as this. With this you run your while loop ones for every input. Until you get the value as you like. If the value is as you wish, you get out of the loop with break
std::cout << "Please choose a NUMBER between 1~9!\n";
while(std::cin >> position){
std::cin.clear();
std::cin.ignore();
if(position < 1 || position > 9){
std::cout << "Please choose a number BETWEEN 1~9!\n";
}else{
break;
}
}
I am teaching an after school club about cin and getline() right now and I know you're suppose to put a cin.ignore() when switching from cin and getline; I also know why we do that, it all makes sense.
However.... A student put cin.ignore() AFTER the getline() call and it still worked as if they put it before getline(), does anyone know why?
What I teach and what I know works.
string answer, line;
cin >> answer;
cin.ignore();
getline(cin, line);
What shouldn't work but does even though cin.ignore is after getline()?
string answer, line;
cin >> answer;
getline(cin, line);
cin.ignore();
Please read carefully how operator>> works, and what ignore() does.
by default, operator>> discards leading whitespace characters before extracting data needed for a value. This can be disabled with std::noskipws.
operator>> for integer types extracts as many characters as possible to interpret them as an integer.
operator>> for a string extracts only non-whitespace characters. Reading stops just before the first whitespace character.
by default, .ignore() discards just a single character.
to trim a line after operator>>, ignore should be used as: .ignore(std::numeric_limits<std::streamsize>::max(), '\n');
This leads to the following cases:
type
input
read effect
remaining input
int
11
11
int
12
12
int
1\n
1
\n
int
1 \n
1
\n
int
13das
13
das
std::string
foo
"foo"
Your first example will fail if line ends with extra spaces.
Your second example may appear to be working if input contains leading whitespace, or other characters which are skipped do not have impact on reading the result (for example: +12 when reading int).
I am trying to take multiple lines of string input (may contain spaces) in c++ using 2D char array but the loop gets terminated without taking any input for n=1 in the code:
When n=2, it takes only one input and when I try to print input[0], it prints blank. But for cout<
char input[100][100];
int n,i;
cout<<"Enter no of lines : ";
cin>>n;
cout<<"Enter "<<n<<" sentences : "<<endl;
for(i=0;i<n;i++)
cin.getline(input[i],100);
This is a common problem when mixing formatted and unformatted input. After a formatted input, the internal buffer is positioned before the first blank character and before the \n. The bullet proof way would be to always use getline and then scan the first line to extract the number of lines. But for such a simple case, it is enough to use a dummy getline after reading the number of line to skip the end of line:
char input[100][100];
int n,i;
cout<<"Enter no of lines : ";
cin>>n;
cin.getline(input[0], 100); // skip the end of line
cout<<"Enter "<<n<<" sentences : "<<endl;
for(i=0;i<n;i++)
cin.getline(input[i],100);
But:
you should always test cin after a read (what if the user types erroneously e instead of 4?)
you should avoid char arrays and always use string in C++ (simpler, cleaner, less error prone)
When you enter number of lines(say 4) you press 4 and then enter key. It is stored as 4\n in stdin that is standard input. When you read using cin.getline() you are reading \n. You will have to use cin.ignore to ignore existing buffer in stdin. However using >> operator is better since it handles newlines.
For multiline input you can input a third parameter to getline(): a delimiter specifying what indicates the end of your input.
Consider this small piece of code:
#include <iostream>
#include<stdio.h>
using namespace std;
int main() {
int a;
while(true){
cin>>a;
cout<<a;
}
return 0;
}
Input
1 2 3 5 7 23
Output
125723
How I thought it will run is:
First iteration
1. Reads the first input ie '1' and stops reading further, right after reading the whitespace.
2.Prints the value 1.
Second iteration
1. Again asks for new input
2. Print that in the second line
But that doesn't happen instead it reads the elements we gave after space
First iteration:
Peek at next character in the stream. It's a digit ('1'), so read it.
Peek at next character in the stream. It's not a digit (' '), so don't read it; store 1 in a and return from >>.
(Output 1.)
Second iteration:
Peek at next character in the stream. It's whitespace (' '), so read and ignore it.
Peek at next character in the stream. It's a digit ('2'), so read it.
Peek at next character in the stream. It's not a digit (' '), so don't read it; store 2 in a and return from >>.
(Output 2.)
And so on ...
The point is that >> does not care about lines. cin is one long input stream of characters (some of which may be '\n'). The only thing you can do is read more characters (and then maybe decide that you don't want to do anything with them).
cin is not necessarily connected to a keyboard. The program that started you gets to decide where cin reads from. It can be a file, a network socket, or interactive user input. In the latter case, reading from cin may block until the user types more input, but it will never cause input to just be dropped.
If you want a sane user interface, always read whole lines and process them afterwards:
std::string line;
while (std::getline(std::cin, line)) {
// do stuff with line
}
I'm writing a simple program that asks a user to input a letter. And then I want him to input a phrase. When it's just a single string I don't have a problem.
char c;
string s;
cin >> c;
cin >> s;
But when I want a phrase
cin >> c;
getline(cin, s);
When I run the program after the user inputs a letter and hits enter I don't get a chance to input the phrase. Of course if I type the character and enter a phrase after a space the program works fine.
On the contrary when I input a character and then enter a single string after a space using the first method, it won't record the string.
Why does it do this?
When ever you write a character and press enter, actually 2 char are send to the buffer: the character itself and \n as the result of the enter key press. Your cin >> c; reads the first character only while \n still remains in the buffer. Since std::getline() reads everything before it encounters a \n character and since \n is the first character it encounters it doesn't read anything and the program terminates. Add a std::cin.ignore(); (to ignore the \n) before std::getline and the code will work.
Since c only takes a character, the enter key that the user presses is given to s so anything other than that is not recorded. Only press a single key and no enter for the character. Or else just use a string anyway.