0

I am using sstream to parse a string. The string contains an arbitrary number of integers separated by spaces. But sstream is not parsing the input properly. Here's my code-

#include<cstdio>
#include<cstring>
#include<vector>
#include<cstdlib>
#include<sstream>
#include<iostream>

using namespace std;

vector<int> val[10010];

int main(){

    int n,i,j,temp;
    stringstream stream;
    string s;
    scanf("%d",&n);
    vector<int>::iterator it;

    for(i=0; i<n; i++){
        getline(cin,s);
        stream.str(s);

        while(1) {
            stream >> temp;
            val[i].push_back(temp);
            if(!stream)
                break;
        }

        for(it=val[i].begin(); it!=val[i].end(); it++)
            printf("%d ",*it);

        printf("\n");
    }
    return 0;
}

Here are the test cases : Code

Abhishek Modi
  • 187
  • 4
  • 17

3 Answers3

1

Not sure if this is your main error, but you have a \n - new line after scanf("%d",&n);, scanf is only grabbing integer, new line is left and getline is not reading your input.

You can ignore this new line with below, just before calling getline:

if ( isspace(cin.peek()) )
  cin.ignore();

also, its better to:

if ( stream >> temp ) {
   // do something with temp
}

now you always add string with previously parsed value as last element.

Also, you should clear stringstream before using it again, otherwise it stays in error state and you are not able to use it. Add this: stream.clear(); before stream.str(s);.

marcinj
  • 48,511
  • 9
  • 79
  • 100
0

Add cin.get (); after your scanf -- this consumes the \n at the end of your line of input where you're reading in n. After that, you'll stop getting nonsense in your vector. cin.ignore(SOME_BIG_NUMBER) might also work, skipping not just the next char (likely \n) but also spaces preceding it.

There's one other fix you need: in the innermost loop, if(!stream) break; must come before val[i].push_back(temp);, or you'll get an extra copy of the last int on your input line.

I further recommend that you either use stream I/O or C-style I/O (printf, scanf) and not both -- but that's not your problem here.

Topological Sort
  • 2,733
  • 2
  • 27
  • 54
  • This is incorrect on several levels. First, `cin.get()` doesn't consume the `'\n'`; it consumes the next character (which might be a trailing space). You absolutely need to use the ignore. Except, of course, there's no point in the first input anyway. And there's no point in putting the read from the stream in the loop, and then using `while`; there are much better ways of writing this. – James Kanze Mar 07 '14 at 18:38
0

What's happening is clear. The first line you read is empty (because you've left the '\n' in the stream when reading the count), then you parse it with stream, ending with stream in a failed state. And once stream is in a failed state, it stays that way, and all further operations are no-ops.

More generally, there are a number of problems with your code:

  • Don't mix C style IO and iostream, especially not on the same file. Sometimes it's unavoidable, when you have to deal with legacy libraries, but don't do it intentionally. In fact, there's never any reason to use C style IO in C++.

  • Don't define all of your variables at the top. Don't define them until you need them. In particular, there's no point in declaring the string stream until you're in the loop (which would avoid the problem you're seeing).

  • Do check that std::getline has succeeded before using the values you have read.

The idiomatic way of doing something like this would use a vector of vectors, with push_back:

std::vector<std::vector<int>> val;

//   and for the loop...
std::string line;
while ( std::getline( std::cin, line ) ) {
    val.push_back( std::vector<int>() );
    std::istringstream parse( line );
    int i;
    while ( parse >> i ) {
        val.back().push_back( i );
    }
}

Except, perhaps, with more error checking. (Did the parse >> i in the while fail because it has read all of the line, or because some one slipped an "abc" in as a number?)

James Kanze
  • 150,581
  • 18
  • 184
  • 329