istringstream

K

k:arel

today i've discovered the istringstream object
i'm trying to read a string and split it up in a number of fields,
consisting of integers and strings

it's for a protocol that sends messages with:
* message code, pe. 1 for HELLO
* message content, pe. 5 (seed)

both field are separated by @+@

/* *********************************************** */
istringstream in;
in.str("1@+@5");

int msgcode=-1;
int seed=-1;
string spacer;

in >> msgcode >> spacer >> seed;

cout<<"msgcode="<<msgcode<<",spacer="<<spacer<<",seed="<<seed<<endl;
/* *********************************************** */

yet, when i run this, the output is:
msgcode=1,spacer=@+@5,seed=-1

the 5 always belongs to the string "spacer"

also replacing the @+@ by a space or taking a char* as data type for
"spacer" doesn't put the 5 in the "seed"
the string "spacer" alway reaches to the end (also if we set there 555
instead of just 5), it's probably because the stream can't tell where
to end the string and start the integer...

has anybody any idea how i could bypass this?
 
R

roberts.noah

k:arel said:
/* *********************************************** */
istringstream in;
in.str("1@+@5");
in >> msgcode >> spacer >> seed;
the string "spacer" alway reaches to the end (also if we set there 555
instead of just 5), it's probably because the stream can't tell where
to end the string and start the integer...

Reading a string gobbles up everything up to any whitespace. I don't
think it will be the best answer to your problem.
 
R

red floyd

k:arel said:
today i've discovered the istringstream object
i'm trying to read a string and split it up in a number of fields,
consisting of integers and strings

it's for a protocol that sends messages with:
* message code, pe. 1 for HELLO
* message content, pe. 5 (seed)

both field are separated by @+@

/* *********************************************** */
istringstream in;
in.str("1@+@5");

int msgcode=-1;
int seed=-1;
string spacer;

in >> msgcode >> spacer >> seed;

cout<<"msgcode="<<msgcode<<",spacer="<<spacer<<",seed="<<seed<<endl;
/* *********************************************** */

yet, when i run this, the output is:
msgcode=1,spacer=@+@5,seed=-1

the 5 always belongs to the string "spacer"

also replacing the @+@ by a space or taking a char* as data type for
"spacer" doesn't put the 5 in the "seed"
the string "spacer" alway reaches to the end (also if we set there 555
instead of just 5), it's probably because the stream can't tell where
to end the string and start the integer...

If you're using VS 2005, this is a known bug in the library.

See this thread for details:
http://groups.google.com/group/micr...hread/64ac882a37ddb1e9/eee6c084d09bf204?tvc=1
 
R

red floyd

Reading a string gobbles up everything up to any whitespace. I don't
think it will be the best answer to your problem.

Ah, good point, I missed that. However, there is also an issue with VS2005.
 
N

Nitin Motgi

Reading a string gobbles up everything up to any whitespace. I don't
think it will be the best answer to your problem.

Noah is right reading string messes you up. Addition of "@+@", is it
required by the protocol or is it something that you have added as a
seperator. If protocol does not require that then you add a seperator
like "+ " (replace @ with space on ight hand side of +). By this when
reading string the stream will stop after getting a space.

-- Nitin Motgi.
 
B

BobR

(e-mail address removed) wrote in message ...
Reading a string gobbles up everything up to any whitespace. I don't
think it will be the best answer to your problem.

k:arel,

Try 'getline()' with a delimiter:

{
std::istringstream isin("25 This is a string\n 09 1876");
int num1(0), num2(0);
std::string thestring;
isin >> num1;
isin.ignore(1); // skip the space
std::getline( isin, thestring, '\n' );
isin >> num2; // leading space ignored
std::cout <<"num1="<<num1<<" thestring="<<thestring
<<" num2="<<num2<<std::endl;
// out: num1=25 thestring=This is a string num2=9
}

That help you k:arel?
Thanks for the use of your post, Mr. roberts. <G>
 
K

k:arel

ok, this did the trick:

i'm free to choose the seperator, but since where sending bash
commands, the seperator should be "weird".

i replaced the spaces bij underscores, so it's clearer:
this works: in.str("1+_5");
this works: in.str("1+_+5");
this works: in.str("1@+@_5");
! mention the spaces !

@red floyd, i'm using KDevelop3 for programming C++ because i'm using
Unix resources in my program.

i also found this solution:
/* *********************************************** */
istringstream in;
in.str("1@+@55");

int msgcode=-1;
int seed=-1;
char ch;
in >> msgcode >> ch>>ch>>ch>> seed;
/* *********************************************** */

yet this solution is NOT user friendly: we won't be able to change the
separator in a normal way then...

though you could (!) solve it like this:
/* *********************************************** */
istringstream in;
in.str("1@+@55");

int msgcode=-1;
int seed=-1;
in >> msgcode;
readSeparator(in, separator);
in >> seed;


void readSeparator(istringstream &in, string separator) {
char ch;

for(int i=0; i<separator.size() ; i++) {
in >> ch;
}
}
/* *********************************************** */


thanks for the replies!
 
K

k:arel

Bob,
your method works fine if the separator is only one character.

My separator is 3 characters: @+@.
As i said before, i'm free to choose any separator, but i must be able
to separate the fields in an obvious way.
I could replace my separator @+@ with an other character, not used.
But this character has to be chosen at first and it's difficult to say
which character is NOT going to be used in any of the commands.
Of the separator @+@, you could say, with a certain certitude, that it
will never be send...
 
B

Ben Pope

k:arel said:
Bob,
your method works fine if the separator is only one character.

My separator is 3 characters: @+@.
As i said before, i'm free to choose any separator, but i must be able
to separate the fields in an obvious way.
I could replace my separator @+@ with an other character, not used.
But this character has to be chosen at first and it's difficult to say
which character is NOT going to be used in any of the commands.
Of the separator @+@, you could say, with a certain certitude, that it
will never be send...

Well then do it properly. Pick an escape character.

Take for example, C strings if you want to have a string containing a
'\' you type it twice "\\". Now, if you see a single instance of that
character, the next character is special. If you see it twice, you want
the original character.

Pick a separator that is, say '@'.

So if your original message contains 2 fields, that are delimiter
separated and the fields are "field1", "fi@ld2", then the encoded
message is "field1@fi@@ld2".

You'll have to use '@' as the delimiter and then if the next field
starts with a @, you have to concatenate it to the current field.

Ben Pope
 
N

Nitin Motgi

k:arel said:
ok, this did the trick:
char ch;
in >> msgcode >> ch>>ch>>ch>> seed;

If the sstream has in.str("1@+@[num]") num is either a
1,2,3, or n digit number. Then you would have to know
in advance how many will be there.
though you could (!) solve it like this:
/* *********************************************** */
istringstream in;
in.str("1@+@55");

int msgcode=-1;
int seed=-1;
in >> msgcode;
readSeparator(in, separator);
in >> seed;

Why don't you take a look at Boost.Tokenizer.

Thank you
Nitin Motgi
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top