1

I've been trying to split up an input string into smaller strings delineated by whitespace. I found this code from here:

stringstream ss ("bla bla");
string s;

while (getline(ss, s, ' ')) {
cout << s << endl;
}

which works just fine. However, if I replace "bla bla" with a variable containing a string:

string userInput;
cin >> userInput;

stringstream ss (userInput);
string s;

while (getline(ss, s, ' ')) {
cout << s << endl;
}

only the first word/char/string prints out. Why is that? Is there a way to fix it? I've looked around at some stringstream questions, but the problem is that I don't really know what I'm looking for.

Community
  • 1
  • 1
user1258934
  • 13
  • 1
  • 4
  • 4
    Please show an example of "a variable containing a string" and initializing the `stringstream` with that. – Xeo Mar 09 '12 at 09:31
  • Looks ok to me: http://ideone.com/1AvVV. – Oliver Charlesworth Mar 09 '12 at 09:42
  • Either don't use `cin ` to initialise `userInput` so you can focus on `getline`, or investigate just what `cin >> userInput;` does, without worrying about `getline`. – Peter Wood Mar 09 '12 at 09:42
  • @LuchianGrigore Really? Could it be a compiler issue then? I was working in Code::Blocks 10.05. I'll pull another IDE real quick and try it then. – user1258934 Mar 09 '12 at 09:43
  • @user1258934 It's not the compiler - it's you. The problem is with `cin`. Just test that bit of code to understand how `cin` works. – Peter Wood Mar 09 '12 at 09:47

2 Answers2

8

Your problem isn't stringstream ss (userInput);, it's the behavior of std::cin. Any whitespace will end the extraction of formatted user input, so the input bla bla will result in one std::string s = "bla" and another string "bla" waiting for extraction.

Use cin >> noskipws >> userInput; instead. If you want to get a line, use std::getline(std::cin,userInput) instead. Have a look at this little demonstration, which compares std::getline to std::cin::operator>> on your input bla bla:

Source:

#include <iostream>
#include <string>

int main(){
        std::string userInput;

        std::cout << "Using std::getline(std::cin,userInput) on input \"bla bla\"." << std::endl;
        std::getline(std::cin,userInput);
        std::cout << "userInput contains \"" << userInput << "\"" << std::endl;

        std::cout << "std::cin >> userInput on input \"bla bla\"." << std::endl;
        std::cin >> userInput;
        std::cout << "userInput contains \"" << userInput << "\"" << std::endl;
        return 0;
}

Result:

Using std::getline(std::cin,userInput) on input "bla bla".
userInput contains "bla bla"
std::cin >> userInput on input "bla bla".
userInput contains "bla"

See also:

Zeta
  • 103,620
  • 13
  • 194
  • 236
  • You sir/madam, are a Godsend. Thank you so much. – user1258934 Mar 09 '12 at 09:47
  • @user1258934 AAAhhhh I was testing with "blabla", not "bla bla", that's why it worked. +1 – Luchian Grigore Mar 09 '12 at 09:48
  • @user1258934: I updated my answer, since I described the behavior but provided a dull solution. I mean, come on, `std::noskipws`? I shouldn't answer any questions without coffee :D... But I guess you already solved the rest (`std::getline`) yourself. – Zeta Mar 10 '12 at 08:43
0

This does what you said:

#include "stdafx.h"
#include <string>
#include <sstream>
#include <iostream>

int _tmain(int argc, _TCHAR* argv[])
{
    std::string test("bla bla");
    std::stringstream stream(test);
    std::string temp;
    while (getline(stream, temp, ' ')) {
       std::cout << temp << std::endl;
    }
    return 0;
}

It is even what you said you did. But since it works - where is the difference to your code?

And for those who do not have a Microsoft Visual C++ compiler handy and do not understand the differences, here's a code snippet:

std::string test("bla bla");
std::stringstream stream(test);
std::string temp;
while (getline(stream, temp, ' ')) {
   std::cout << temp << std::endl;
}

the includes required by that snippet are: <string>, <sstream> & <iostream>. Please insert it into the required method.

Zeta
  • 103,620
  • 13
  • 194
  • 236
Tobias Langner
  • 10,634
  • 6
  • 46
  • 76
  • 3
    On Stack Overflow, it is better to present standard C++, rather than Microsoftized C++ (`stdafx.h`, `_tmain`, `_TCHAR`)... – Oliver Charlesworth Mar 09 '12 at 09:46
  • @Chalesworth: I'd agree if the code that matters requires changes to run on a different compiler - but in this case it does not (see modification of the post). I wanted to post an example that I compiled and tested. – Tobias Langner Mar 09 '12 at 09:59