SOVLED!!! C++, am I using stringstream correctly?

Started by
15 comments, last by darenking 18 years, 8 months ago
I wonder if anyone can tell me if I'm using stringstream correctly. It seems to work but seven lines of code seems a lot just to read text from a .txt file into a string, convert it to an int and add it to a vector of ints. Here's the code. My program already knows that the string can be converted to an int, ie the string is "123" rather than "hello".

	vector<int> values;
	string next;
	file >> next;
	stringstream ss(next);
	int value;
	ss >> value;
	values.push_back(value);


Is there anything I'm doing twice or doing that I don't need to do? Is there a more compact way of doing things? (Without making it more complex/less clear just for the sake of saving space.) [Edited by - darenking on August 6, 2005 10:15:35 AM]
Advertisement
Do you realize that you don't actually need the stringstream? A file stream can do the same things, including converting to an int.

        vector<int> values;        int value;	file >> value;	values.push_back(value);
It's common to create a wrapper function around the stringstream functionality.

boost provides boost::lexical_cast, although it isn't that difficult to write your own if you don't want to use boost.
Quote:Original post by pi_equals_3
Do you realize that you don't actually need the stringstream? A file stream can do the same things, including converting to an int.

*** Source Snippet Removed ***


Is this basically because, in this case, my program knows it is to receive an int? I simplified my routine in the example above; in actual fact there are occasions when it knows that it is to receive and int and occasions when it may receive either an int or some text (a filename for example). Presumably on the occasions when the program does not know what is next in the file, I will have to use stringstream?
No, it's just that stringstreams and file streams provide the same interface; you only need to set up a stringstream when you've already read the data into a string anyway - sometimes this is useful for more complicated parsing, or simply for organizational purposes.

If you try to read a foo off of a file stream when the data "at the front" can't be interpreted as a formatted foo, then no data will be extracted, and the stream will "fail" to indicate the error. To clear the "fail" flag, call the stream's .reset(); with console I/O you would normally then .ignore() (or read and discard) a line of input, because of cin being line buffered and a need to try again. However, you can just as easily try to read into a differently-typed variable instead, if that's appropriate for your program behaviour. (Reading into a char, char*, or std::string should always succeed, except of course at end of file.) Oh, and yes you can do this with file streams too :)
Quote:Original post by Zahlman
you only need to set up a stringstream when you've already read the data into a string


I guess that's the situation here (below). My program doesn't know (at this point) whether it is going to receive text or an int, so it reads it into a string, then copies it into a stringstream called buffer (I think), and tries to convert it into an int. If it fails, it stores it as a string.

	file >> text;	stringstream buffer(text);	if ( buffer >> value )	{		values.push_back(value);		amount++;	}	else	{		phrases.push_back(text);	}


Unless there is a simpler way?
I'd have to try this to make sure, but if you try to extract a string into an int, I don't think it will fail. I think it will just give you garbage.

And that still doesn't make the stringstream necessary. You could just as easily attempt to extract from a file into an int.

I think what you'll need to so is extract into a string and determine if it's a number before converting it. I don't know the best way to do that, but maybe someone else does.
At the moment I'm reading it from the file into a string then converting it if needed. It would be better theoretically to try to read it from the file into an int, and if it fails, to read it as a string instead. But as you say it probly just reads in as garbage rather than fails.
Quote:Original post by darenking
Unless there is a simpler way?


Something like:

int value;std::string phrase;if (!(file >> value)) {  // if reading failed - (see below for explanation)  // then we clean up, and read a string instead.  file.clear();  // don't "ignore"; we want to read the data that wasn't an int  file >> phrase;  phrases.push_back(phrase);} else {  // it worked; store it  values.push_back(value);  amount++;}


The result of an operator>> call on the file stream is a reference to the stream itself (this is how "chaining" works). Also, the stream object can be evaluated in a boolean context; it is "true" iff the stream is "good" (has not been put into the fail state, reached EOF or suffered some other serious error). Here, we negate the expression, which is then interpreted in boolean context (it would be anyway, because of being used for an if statement) - thus the meaning "try to read in; if failed to do so {". A common C++ idiom. :)
What does file.clear() do?

This topic is closed to new replies.

Advertisement