0

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?

Little_idiot
  • 115
  • 7

4 Answers4

2

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.

Dietmar Kühl
  • 141,209
  • 12
  • 196
  • 356
0

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";
            }
        }
    }
}
Gardener
  • 2,427
  • 1
  • 9
  • 21
0

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

Allamo Olsson
  • 193
  • 1
  • 10
  • Re: " cin just extracts the word" -- `std::cin` doesn't extract anything. `>>` and `getline` extract characters from an input stream; when you pass `std::cin` to those functions they extract characters from it. – Pete Becker Nov 09 '18 at 14:36
0

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.

Mark Ransom
  • 271,357
  • 39
  • 345
  • 578