tags:

views:

78

answers:

3

Here is a sample program that uses stringstream. The goal is to accept lines from the user(standard input) and print each word in a separate line.

int main()
{

    std::istringstream currentline;
    std::string eachword;
    std::string line;

    // Accept line from the standard input till EOF is reached
    while ( std::getline(std::cin,line) )
    {
        currentline.str(line); // Convert the input to stringstream
        while ( currentline >> eachword ) // Convert from the entire line to individual word
        {
            std::cout << eachword << std::endl;
        }
        currentline.clear();
    }
    return 0;
}

I'm wondering, is there a way , I can avoid the intermediate string variable(object), line and directly store the user input to the currentline (istringstream object).

Note:

I know, the following solution already.

while ( std::cin >> eachword)
{
    std::cout << eachword << std::endl;
}
A: 

If you want to simplify the first solution,

while ( currentline(line) >> eachword )
Jacob
Jacob, when I try, it didn't even compile.
+1  A: 

std::getline needs a string reference argument, and that's where it places the line it has obtained, so of course you can't avoid passing such an argument (and still use that function). You could elegantly encapsulate the construct, if you need it often -- e.g.:

bool getline(std::istream& i, std::istringstream& current)
{
    std::string line;
    if ( std::getline(i, line) ) {
        current.str(line);
        return true;
    }
    return false;
}
Alex Martelli
Encapsulate, surely?
anon
Nice function. But I believe, you intend to take istream as a parameter. In that case, shouldn't the if statement be like this. if ( std::getline(i,line) )
@Neil and @nsivakr, you're both right, tx -- +1, and editing to fix.
Alex Martelli
A: 

I assume you want to not use an intermediate object to prevent unnecessary copying?

You can achieve the same affect by explicitly setting the stream buffers buffer area.

int main()
{
    std::string line;
    std::istringstream currentline;
    std::string eachword;

    // Accept line from the standard input till EOF is reached
    while ( std::getline(std::cin,line) )
    {
        // Set the buffer without copying.
        currentline.clear();
        currentline.rdbuf()->pubsetbuf(&line[0], line.length() );

        while ( currentline >> eachword )
        {
            std::cout << eachword << std::endl;
        }
    }
    return 0;
}

Because of the order of destruction. You just need to make sure the istringstream is destroyed before the object you are using as a buffer. So you need to re-arrange the declarations at the top of main() to make sure that line is created first and thus will be destroyed last (otherwise the destructor of the istringstream has the potential for accessing the memory of a free'ed object.

Martin York
Love the solution. But when I ran the program, it doesn't print the words. In other words, the inner while loop, fails every time.
@nsivakr: Fixed. Just because you reset the buffer does not mean the flags are reset. Added back the call to clear to reset the flags.
Martin York
@Martin -> Still doesn't work for me when I run it.