Reading two line continuously using getline function in c++ - c++

I was learning how to read strings with getline function.
I know that getline function read string as far as we don't hit enter or the size value in the getline parameter go cross. As far as I tried getline function to read one line of string I had not faced any problem.
But when I was trying to read two line of string one after another in two different char array i got the output that was not expected to me.
To understand my question follow bellow lines
#include <iostream>
using namespace std;
int main()
{
char line1[10];
char line2[10];
cin.getline(line1,7);
cin.getline(line2,7);
cout << "\nline1 =" << line1 <<endl;
cout << "line2 =" << line2 <<endl;
}
When I ran the above program it ask me for input then I gave orange as first input and hit the enter button.
Next it ask me to give the second input .then i gave banana and hit the enter button .in this case it produce the result i expected .But if enter oranges for the first input it does not wait for me to enter the second input.
As a result line1 store orange but line2 remains blank.
Now my question is that there is no wrong with line1 storing orange. But I don't understand why the line2 remains blank should not it contain the data that remains after line1 take input I mean should not line2 contain s as value.
Because orange is a 6 digit word so getline will stores the first six digit after then a null character will be added as I set the size of geline 7.
Then other remaing data will be assigend in the next call of getline function.So should not s stored in line2 as after s a new_line character is read for the first time.
Why will be line2 remain blank and why the screen doesn't stop for taking input after giving the first input?

std::istream::getline is being overloaded with data.
According to cppreference,
Behaves as UnformattedInputFunction. After constructing and checking the sentry object, extracts characters from *this and stores them in successive locations of the array whose first element is pointed to by s, until any of the following occurs (tested in the order shown):
end of file condition occurs in the input sequence (in which case setstate(eofbit) is executed)
the next available character c is the delimiter, as determined by Traits::eq(c, delim). The delimiter is extracted (unlike basic_istream::get()) and counted towards gcount(), but is not stored.
count-1 characters have been extracted (in which case setstate(failbit) is executed).
Emphasis mine.
cin.getline(line1,7);
// ^ This is count
can read only 6 characters with the 7th reserved for the null terminator. "oranges" is seven characters, and this places cin in a non-readable error state that must be cleared before reading can be continued. Reading of the second line
cin.getline(line2,7);
instantly fails and no data is read.
The obvious solution is
cin.getline(line1, sizeof(line1));
to take advantage of the whole array. But...
Any IO transaction should be tested for success, so
if (cin.getline(line1, sizeof(line1)))
{
// continue gathering
}
else
{
// handle error
}
is a better option.
Better still would be to use std::getline and std::string to almost eliminate the size constraints.

Related

in c++ program after pressing enter , "cin" will feed all Variables

I have a program that takes two numbers and shows them on the screen.
However, when I hit "enter" after I input the first number, my program shows the answers before letting me input the second number.
Why does this happen?
int main()
{
int n1;
float n2;
cin>>n1;
cin>>n2;
cout<<"int n:"<<n1<<endl<<"float n:"<<n2;
return 0;
}
I wanna input 0.25 and 35 but when I write 0.25 and hit enter suddenly shows the answer "int: n:0 float n:0.25" it doesn't let me write second num. my os is Win10 and this program compiled with DevCpp
It works when both variables are ints.
There is no difference between cin>>n1; cin>>n2; and cin >> n1 >>n2. Enter key only serves as signal to sychronize input buffer and stream buffer. cin doesn't input per line, it parses buffer when there is available volume of data. If parse incomplete, it waits. If parse can't be done, it stops and state bit changes. To continue parsing you have either ignore or clear part or whole buffer content.
Something wrong was entered in first line, causing cin to go into bad() state. Edge case might happen if you're running program through a remote terminal, some incorrect character could slip in, e.g. ^M generated by new line from Windows would break cin stream on Linux. That's also case if you input from a file which was saved on different platform. On Windows line ends consist of two characters, #10 and #13. On linux steams expect only #13 as a new line and buffer flush signal, #10 is an unexpected character.
Edit (after OP gave information about input data):
"0.25" would be parsed as "0" and ".25", that expected and documented stream behavior. Parsing for n1 had stopped as soon as stream encountered character which doesn't fit int pattern, which could be space, end of line, alphabetic or punctuation. Period considered a punctuation in this case
Then it tries to get a float from stream input and buffer contains ".25". It's a legal float notation and it gets assigned to n2.
When you have both "int", you cannot get second value at all with same input, it always will be 0, because cin locks up in bad state, i.e. method its istream::good() returns false. You have to check state of stream after reading variables. Any further formatted reading that wouldn't be able to parse .25 wouldn't advance stream past that point.
If you want to read from stream exclusively line by line, you have to use istream::getline() method to get the string. There is also method get which can acquire content of stream and ignore which allows to discard part of stream.

C++ multiple cin.get()

Could seem an old question, but the problem here isn't the use of TWO cin.get(), but of more than two! if I write (in DEV C++)
I get just one input request (s) and then end program. Now, I expected having at least two request of cin, because I expected:
char s[50];
char t[100];
char r[100];
char f[100];
cin.get(s,49);
cin.get(t,99);
cin.get(r,99);
cin.get(f,99);
I expeted at least 2 input request, because:
first cin: buffer empty,I insert the string s and \n
second cin: I have in buffer \n still, then t=\n without input request
third cin: buffer empty, I insert the string r and \n
fourth cin: I have in buffer \n still, then f=\n without input request
But I have just the input request for s string!
why have I just one input request?the buffer didn't clean with second cin.get, letting third cin.get work properly? Thanks
t does NOT equal '\n'. It's empty. .get(char*,int) will never remove the '\n' from the buffer.
Worse, the attempt to read to t will set cin to a fail state since nothing could be read, which will cause all subsequent reads of any sort from cin to fail immediately without even trying until you .clear() the fail state.
This is surprising behavior, but you seem to have already guessed at most of it as per your last sentence in the question, so, Good Job! You're learning!
http://en.cppreference.com/w/cpp/io/basic_istream/get

Meaning of cin.fail() in C++?

while (!correct)
{
cout << "Please enter an angle value => ";
cin >> value; //request user to input a value
if(cin.fail()) // LINE 7
{
cin.clear(); // LINE 9
while(cin.get() != '\n'); // LINE 10
textcolor(WHITE);
cout << "Please enter a valid value. "<< endl;
correct = false;
}
else
{
cin.ignore(); // LINE 18
correct =true;
}
}
Hi, this is part of the code that I have written.
The purpose of this code is to restrict users to input numbers like 10,10.00 etc,
if they input values like (abc,!$#,etc...) the code will request users to reenter the values.
In order to perform this function( restrict user to input valid valus), I get some tips and guides through forums.
I think is my responsibility to learn and understand what these codes do... since this is the first time I use this code.
can someone briefly explain to me what does the codes in
line 7,9,10, and 18 do? Especially line 10. I got a brief idea on others line just line 10 I don't know what it did.
Thanks for your guides, I appreciate that!
cin.fail() tells you if "something failed" in a previous input operation. I beleive there are four recognised states of an input stream: bad, good, eof and fail (but fail and bad can be set at the same time, for example).
cin.clear() resets the state to good.
while(cin.get() != '\n') ; will read until the end of the current input line.
cin.ignore(); will skip until the next newline, so is very similar to while(cin.get() != '\n');.
The whole code should check for end of file too, or it will hang (loop forever with failure) if no correct input is given and the input is "ended" (e.g. CTRL-Z or CTRL-D depending on platform).
// LINE 7: cin.fail() detects whether the value entered fits the value defined in the variable.
// LINE 18: cin leaves the newline character in the stream. Adding cin.ignore() to the next line clears/ignores the newline from the stream.
For line 7 and line 9, read the document.
while(cin.get() != '\n'); // LINE 10
in the while, it tests whether the line cin.get() is an empty line, i.e, containing just the new line.
Line 7: test if entered data is correct (can be read as decltype(value)). cin.fail() is always true if some error with the stream happened. Later, in
line 9: you clear cin state from bad to previous, normal state. (recover after the error). You cannot read data anymore until recovering from the bad state.
Line 10: you read until the end of line. Basically you skip one line from the input
Line 18: this line executes only if entered data is corrected. It reads and discards one line from stdin.
while(cin.get() != '\n'): All string in c are null terminated. This means that \n is the end of all the string objects. Lets say you have string "this" for c it is this\n, each alphabet being stored in a char type. Please read along
http://www.functionx.com/cpp/Lesson16.htm
cin.fail(): cin.fail() detects whether the value entered fits the value defined in the variable.
read:http://www.cplusplus.com/forum/beginner/2957/
cin.ignore(): Extracts characters from the input sequence and discards them
http://www.cplusplus.com/reference/istream/istream/ignore/
I know it's not usual in Stack Overflow to just list links, so I'll give a bit more detail, but this answer really boils down to a bunch of links.
For line 7, just google cin.fail. Here's a good reference, and what it says:
Returns true if either (or both) the failbit or the badbit error state flags is set for the stream.
At least one of these flags is set when some error other than reaching the End-Of-File occurs during an input operation.
failbit is generally set by an operation when the error is related to the internal logic of the operation itself; further operations on the stream may be possible. While badbit is generally set when the error involves the loss of integrity of the stream, which is likely to persist even if a different operation is attempted on the stream. badbit can be checked independently by calling member function bad:
One line translation: it tells you if there was an unexpected error while trying to read the input stream.
You can find similar references for cin.ignore, cin.clear and cin.get. The quick summary:
cin.ignore - ignore one single character present in the stream.
cin.clear - clear any error flags in the stream
cin.get - get one character at a time, until you hit the newline '\n' character.
The standard input stream (cin) can fail due to a number of reasons.
For example, if value is an int, and the user enters a large number like
124812471571258125, cin >> value will fail because the number is too big to fit inside an int.
But:
There is a much simpler way to do what you want. You want the user to enter only valid floating-point values, e.g. 10 or 10.00, but no characters, right? So you can just do this:
double value;
cout << "Please enter an angle value: " << endl;
while (!(cin >> value)) { //Since value is a double, (cin >> value) will be true only if the user enters a valid value that can be put inside a double
cout << "Please enter a valid value:" << endl;
}
This does the same thing that your code does, but much more simply.
If you're interested in what other things can cause cin to fail, look here:
http://www.cplusplus.com/forum/beginner/2957/

Run Time Error: Program skipping prompt for second and third names [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Program is skipping over Getline() without taking user input
Alright, so I have a program that is running and at the start it prompts you for the data fill the data members. The program does this for 3 different objects.
My problem is that, at run time, after inputting data for the fist object the program proceeds to skip input for the second name and goes straight to the next option. It does the same thing for the third option's name. It also does this when you get the chance to change the data.
"Enter CD Name: Microsoft Word
1-Game
2-Word
3-Compiler
4-Spreadsheet
5-Dbase
6-Presentation
Enter the number that corresponds with the CD's Type: 2
Input CD Cost: 15.23
Enter CD Name: 1-Game <- ((Skips the input part and takes you directly to the menu!))
2-Word
3-Compiler
4-Spreadsheet
5-Dbase
6-Presentation
Enter the number that corresponds with the CD's Type:"
The issue is most likely in my member function, but I'm not sure what the issue is.
Here's my member function code:
void CDX::LoadInfo() //Prompts, validates and sets data members
{
cout << "Enter CD Name: ";
getline(cin, Name);
int choice=0;
do
{ cout << "1-Game\n2-Word\n3-Compiler\n4-Spreadsheet\n5-Dbase\n6-Presentation" << endl;
cout << "Enter the number that corresponds with the CD's Type: ";
cin >> choice;
} while ((choice <1)||(choice>6));
switch(choice)
//Code for case-switch statement goes here)
So what am I missing? Is this a buffer issue or am I prematurely ending the code in some way that causes it to skip?
The conversion of a number stops when it finds a character that can't be converted.
In that case, the character is '\n'
When you use getline to read a line, this character is read and discarded, but when you read a number, it is read (to know if the number continues or not) and if it is not part of the number, it is left in buffer for the next read.
Example:
If you write:
"29312"
and press enter, your buffer will be filled with
"29312\n".
If you use cin >> number, to read stdin, it will consume the digits, but will left in the buffer the "\n".
In the next time you call getline, it will read an empty line that was left in the buffer.
I think it's because the first 'getline(cin, Name)' gobbles up the last newline keypress. When you enter the cost and press ENTER, the call to getline is completed.
You can keep an extra getline after taking the cost so that it consumes the newline. Then, I think, it will run correctly.
You have read the "CD Cost", but the newline remains in the input buffer. Skip whitespace before reading the CD name:
ws(cin);

Trying to Read a Line of Keyboard Input in C++

I mam trying to complete a college assignment in C++ and am having trouble with what should be a very basic operation. I am trying to read a string of characters from the keyboard. This is the relevant code:
string t;
cout << endl << "Enter title to search for: ";
getline(cin, t, '\n');
I understand, that the last line is supposed to read the input buffer (cin , in this instance) and store the character in the 't' string until it reaches a new line character and then continue the program flow.
However, when I run my code in XCode, it just sort of jumps over the getline function and treats 't' as an empty string.
What's going on? I tried using cin >> t but that just read characters forever - Why cant I get this to behave?
The reason that the input operation apparently is skipped, is most probably (that means, ignoring possible peculiarities of a bugsy XCode IDE) that you have performed some input earlier and left a newline in the input buffer.
To fix that, make sure that you have emptied the input buffer after each input operation that logically should consume a line of input.
One easy way is to always use getline into a string, and then use e.g. an istringstream if you want to convert a number specification to number type.
Cheers & hth.,
From the docs page it looks like you want
cin.getline(t,256,'\n');
or something similar.
This sounds like an issue with the way Xcode is running your program. Try running your program directly from the terminal, and see if this is sufficient to fix your issue.