cin.get() in a loop - c++

I was trying to read from standard input. The first line is the number of lines that I will read. The lines that I read next will be printed again. Here is the code:
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
for (unsigned int i = 0; i < n; ++i)
{
char a[10];
cin.get (a, 10);
cout << "String: " << a << endl;
}
return 0;
}
When I run it and give number of lines, the program exits. I haven't figured out what's going on, so I've decided to ask it here.
Thanks in advance.

Mixing formatted and unformatted input is fraught with problems. In your particular case, this line:
std::cin >> n;
consumes the number you typed, but leaves the '\n' in the input stream.
Subsequently, this line:
cin.get (a, 10);
consumes no data (because the input stream is still pointing at '\n'). The next invocation also consumes no data for the same reasons, and so on.
The question then becomes, "How do I consume the '\n'?" There are a couple of ways:
You can read one character and throw it away:
cin.get();
You could read one whole line, regardless of length:
std::getline(std::cin, some_string_variable);
You could ignore the rest of the current line:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
As a bit of related advice, I'd never use std::istream::get(char*, streamsize). I would always prefer: std::getline(std::istream&, std::string&).

Adding a cin.get() before cin.get(a, 10) will solve your problem because it will read the remaining endline in the input stream.

I think it is important to know this when you are using cin : http://www.cplusplus.com/forum/articles/6046/

Related

Need to ask for car make in C++ program [duplicate]

In the following code, getline() skips reading the first line.
I noted that when commenting the "cin >> T" line, it works normally. But I can't figure out the reason.
I want to read an integer before reading lines! How to fix that?
#include <iostream>
using namespace std;
int main () {
int T, i = 1;
string line;
cin >> T;
while (i <= T) {
getline(cin, line);
cout << i << ": " << line << endl;
i++;
}
return 0;
}
cin >> T;
This consumes the integer you provide on stdin.
The first time you call:
getline(cin, line)
...you consume the newline after your integer.
You can get cin to ignore the newline by adding the following line after cin >> T;:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
(You'll need #include <limits> for std::numeric_limits)
Most likely there is a newline in your input file, and that is being processed immediately, as explained on this page:
http://augustcouncil.com/~tgibson/tutorial/iotips.html
You may want to call cin.ignore() to have it reject one character, but, you may want to read more of the tips, as there are suggestions about how to handle reading in numbers.
This line only reads a number:
cin >> T;
If you want to parse user input you need to take into account they keep hitting <enter> because the input is buffered. To get around this somtimes it is simpler to read interactive input using getline. Then parse the content of the line.
std::string userInput;
std::getline(std::cin, userInput);
std::stringstream(userInput) >> T;

Does getline() not extract the delimiter?

So I was taking input some integers and then taking input some sentences.
This code works fine:
#include<bits/stdc++.h>
using namespace std;
main(){
int c,b,n,i;string s;
cin>>n>>b>>c;
for(i=0;i<n;i++){
cin>>ws;
getline(cin,s,'\n');
cout<<s;
}
}
Example:
3 3 3
This is weird
This is weirdDefinitely makes
Definitely makesNo sense
No sense
However, when I try to omit the cin>>ws inside the forloop, it doesn't work properly, eg this code segment,
#include<bits/stdc++.h>
using namespace std;
main(){
int c,b,n,i;string s;
cin>>n>>b>>c;
for(i=0;i<n;i++){
getline(cin,s,'\n');
cout<<s;
}
}
Example:
3 3 3
This is weird
This is weirdDefinitely makes
Definitely makes
..and terminates there instead of taking all three inputs.
Why is that? cin>>ws extracts all whitespace from the input but isn't getline() doing that too? So why does it not work properly when I omit cin>>ws in the forloop?
std::getline() extract characters until it extracted the first delimiter character (by default '\n'). The delimiter is not stored in the result but it is extracted. It does not extract whitespace in general or multiple delimiter characters.
As an aside: always check whether input works after trying to read a value.
In the example printed, the issue is is that after formatted input, i.e., using the >> operator, whitespaces are not extracted. That is, the first calls to std::getline() extracts the empty string terminated by the initial newline. It generally is necessary to extract trailing whitespace when switching between formatted and unformatted I/O. That is, You'd want code like
if (cin>>n>>b>>c >> std::ws) {
for(i=0;i<n;i++){
if (getline(cin,s,'\n')) {
cout << "i=" << i << ":'" << s << "'\n";
}
}
}
I can't recommend input operations without adding check for success. The output is changed to make it more easily visible what is going on: try the code with/without this particular std::endl to see what is happening.
When you use cin >> it doesn't remove any whitespace after the input. This means the newline that terminated the first 3 inputs is still in the buffer, waiting to be read by the first getline. Since there's nothing before the newline, the first getline delivered an empty string. Your output should have included a newline so you could have seen the empty line, then it would have made sense.
Originally the code you posted showed a cin >> ws just before the for loop which would have eliminated this problem.
The default delimiter for getline() is '\n', so there is no need to include that in the getline call, though, it should not change the functionality.
See for example Same as getline(input, str, input.widen('\n')), that is, the default delimiter is the endline character.
The change in formatting from the integer input to the getline() input leaves some whitespace (endl) after the integer as explained by #DietmarKühl.
You can change the getline() call to eliminate the delimiter to
getline(cin,s);
which will cause getline() to use '\n' as the default delimiter.
I have modified the 'n' variable to count and removed the other integers to make the code a little simpler to read:
#include <iostream>
int main()
{
int i; // index
int count; // number of strings to accept
std::string str;
std::cout << "Input the number of strings you would like me to process: " << std::endl;
std::cin >> count;
if (std::cin >> count >> std::ws) {
for (i = 0; i < count; i++) {
if (getline(std::cin, str)) {
std::cout << "i=" << i << ":'" << str << "'\n";
}
}
}
}
Cin doesn't extract all white spaces, it just gets the first word until the first white space. It is like having a getline with a space delimiter(not quite but close to).
Getline takes the whole line and has the default '\n' delimiter like mentioned above.
Ex:
string a = "Stack Overflow is awesome";
can give you Stack and getline will give you everything at that line

Program is printing unexpected blank lines [duplicate]

This question already has answers here:
Using getline(cin, s) after cin [duplicate]
(13 answers)
Closed 7 years ago.
Consider this code:
#include <iostream>
#include <string>
using namespace std;
int main(){
int n = 1;
string data[13];
while(n > 0){
cin >> n;
for(int i = 0; i < n; i++){
getline(cin,data[i]);
cout << data[i] << endl;
}
}
}
i compiled this in cppdroid on my android. I want to hold n lines in the array. (n <= 13). Everything is fine about that. But when I input an integer in the first line of program, it prints one blank line and on the third line the program takes input for lines. My console window looks like this:
2
This is line 1.
This is line 1.
And this is line 2.
And this is line 2.
I want to remove unwanted spaces.
The
cin >> n;
consumes only the digits you've entered, and leaves a newline (at the least) in the input buffer.
This newline is then read and output by the first executed
getline(cin,data[i]);
cout << data[i] << endl;
To avoid it you can use getline of a string also for the integer input, and e.g. convert to integer via stoi. Or, less robust, you can call the ignore method on the stream to ignore everything up to and including the next newline. It's less robust because formatted input of an integer can put the stream in an error mode where it ignores further input operations until the error mode is cleared.
Re the array, better use a std::vector. Then you don't need to decide on a fixed capacity.
cin >> n reads the number but leaves the newline in the input stream. Your first call to getline reads that, so you start up with an empty line.
The problem is you are mixing calls to getline() with the use of the operator >>.
Remember that operator >> ignored leading white space so will correctly continue across lines boundaries. But stops reading after the input has successfully been retrieved and thus will not swallow trailing '\n' characters. Thus if you use a getline() after a >> you usually get the wrong thing unless you are careful (to first remove the '\n' character that was not read).
The trick is to not use both types of input.
If you're using getline after cin >> yourdata, you need to flush the newline out of the buffer in between.
#include <iostream>
#include <string>
using namespace std;
int main(){
int n = 1;
string data[13];
while(n > 0){
cin >> n;
cin.ignore(10,'\n'); // insert this into your code
for(int i = 0; i < n; i++){
getline(cin,data[i]);
cout << data[i] << endl;
}
}
return 0;
}

Reading sentences as string inputs from users

I have been trying to implement a simple code which takes a sentence as an input from the user, stores it in a string and displays it back.
Here are the issues:
1. When T = 1, the program exits immediately.
2. When T>1, the loop runs for only T-1 times.
I think the usage of cin to store the value of T is an issue here. Is the value of T entered being stored as a string due to some buffer capacity of cin?
#include <iostream>
#include <string>
int main()
{
int T;
std::cin >> T;
while (T--)
{
std::string song;
getline(std::cin, song);
std::cout << song << std::endl;
}
return 0;
}
How do you terminate the input that becomes T? With a newline. What happens with that newline after you read into T? It's still left in the input buffer. What will happen when you next call std::getline, what is the first character it will read? The newline, and what happens next? The loop iterates and then T is zero (for the first case where T was originally 1) and the loop and then the program exits.
The solution to this problem is to ignore characters up to and including the newline.
Add a getchar after cin as the \n after the input of T stays in buffer.
std::cin >> T;
getchar();
This is a strange way to do it. So you ask the user to tell the program, before any other input, how many lines will follow? Why not simply:
std::string s;
while (getline(std::cin, s)) {
std::cout << s << std::endl;
}
(This will simply echo every line (press enter to end the line) until end-of-file (Ctrl-d).
Either way, the problem with your code is the while (T--): so why don't you try to see what your T is, and what your getline gives you on each iteration? (I will let you figure it out on your own). Why not use the idiomatic:
for (int i = 0; i < T; ++i)
?
P.S. If you want to read sentences, and not lines, you might want to consider reading up to a delimiter (for example .). getline will do that for you, too:
getline(std::cin, s, '.');

Why getline skips first line?

In the following code, getline() skips reading the first line.
I noted that when commenting the "cin >> T" line, it works normally. But I can't figure out the reason.
I want to read an integer before reading lines! How to fix that?
#include <iostream>
using namespace std;
int main () {
int T, i = 1;
string line;
cin >> T;
while (i <= T) {
getline(cin, line);
cout << i << ": " << line << endl;
i++;
}
return 0;
}
cin >> T;
This consumes the integer you provide on stdin.
The first time you call:
getline(cin, line)
...you consume the newline after your integer.
You can get cin to ignore the newline by adding the following line after cin >> T;:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
(You'll need #include <limits> for std::numeric_limits)
Most likely there is a newline in your input file, and that is being processed immediately, as explained on this page:
http://augustcouncil.com/~tgibson/tutorial/iotips.html
You may want to call cin.ignore() to have it reject one character, but, you may want to read more of the tips, as there are suggestions about how to handle reading in numbers.
This line only reads a number:
cin >> T;
If you want to parse user input you need to take into account they keep hitting <enter> because the input is buffered. To get around this somtimes it is simpler to read interactive input using getline. Then parse the content of the line.
std::string userInput;
std::getline(std::cin, userInput);
std::stringstream(userInput) >> T;