C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

trouble converting a string to numbers using stringstreams
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Angelo
Guest





PostPosted: Fri Sep 23, 2005 5:44 pm    Post subject: trouble converting a string to numbers using stringstreams Reply with quote



I have a string which I need to convert to integers. I was thinking
that stringstreams would be the best way to convert them, but I am
having trouble. Here's a simple example:

#include <sstream>

int main()
{
// string format: !AATTCCFF
// '!' just need to convert this to a char
// AA, TT, CC, FF are 2-byte unsigned hex (00-FF)
std::string strInput = "!01020304";
std::istringstream strStream( strInput );

unsigned short int A,T,C,F;
char Exclamation;

// I know this is not correct
strStream >> Exclamation >> A >> T >> C >> F;

return 0;
}

I couldnt find any examples on the web using stringstreams that are
similar to this. Somehow, I need to place 1-char into Exclamation, and
then use the next 2 for A, 2 for T, 2 for C, and 2 for F.

Am I simply using the wrong construct here? If not, could somebody
suggest how to accomplish this?

thanks
Angelo


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
kwikius
Guest





PostPosted: Sat Sep 24, 2005 8:15 pm    Post subject: Re: trouble converting a string to numbers using stringstrea Reply with quote



Angelo wrote:
Quote:
I have a string which I need to convert to integers. I was thinking
that stringstreams would be the best way to convert them, but I am
having trouble. Here's a simple example:

[cut]

Quote:
std::string strInput = "!01020304";

white space is required between the unsigned shorts
try changing to:

std::string strInput = "!1 2 3 4";
or "! 1 2 3 4"
or "!t 1n2tttttnt 3 4n"

etc

regards
Andy Little


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Marco Jez
Guest





PostPosted: Sat Sep 24, 2005 8:15 pm    Post subject: Re: trouble converting a string to numbers using stringstrea Reply with quote



Quote:
Am I simply using the wrong construct here? If not, could somebody
suggest how to accomplish this?

There are plenty of ways to accomplish this. For example you can read a
single 32-bit hex number and then extract AA..FF from it:

unsigned int temp;
strStream >> Exclamation >> std::setbase(16) >> temp;
unsigned short AA = 0xFF & (temp >> 24);
unsigned short TT = 0xFF & (temp >> 16);
unsigned short CC = 0xFF & (temp >> Cool;
unsigned short FF = 0xFF & temp;

Note that int must be at least 32 bits in length. If you want a more
portable and flexible solution you can read and decode characters by
yourself, for example by defining a new data type to hold the value of AA,
TT, etc. and providing an operator >> for that type.

Cheers,
Marco


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
BobR
Guest





PostPosted: Sat Sep 24, 2005 8:21 pm    Post subject: Re: trouble converting a string to numbers using stringstrea Reply with quote


Angelo wrote in message
<1127427498.003252.36580 (AT) g44g2000cwa (DOT) googlegroups.com>...
Quote:
I have a string which I need to convert to integers. I was thinking
that stringstreams would be the best way to convert them, but I am
having trouble. Here's a simple example:

#include <sstream
int main(){
// string format: !AATTCCFF
// '!' just need to convert this to a char
// AA, TT, CC, FF are 2-byte unsigned hex (00-FF)
std::string strInput = "!01020304";
std::istringstream strStream( strInput );
unsigned short int A,T,C,F;
char Exclamation;
// I know this is not correct
strStream >> Exclamation >> A >> T >> C >> F;
return 0;
}

I couldnt find any examples on the web using stringstreams that are
similar to this. Somehow, I need to place 1-char into Exclamation, and
then use the next 2 for A, 2 for T, 2 for C, and 2 for F.

Am I simply using the wrong construct here? If not, could somebody
suggest how to accomplish this?
thanks
Angelo


It's not hard, just tedious.
Look-up:
// ----------
Method: istream& istream::get (char& c)
Read a single character from the input stream, into &c.

Method: istream& istream::getline (charptr, int len [, char delim])
Read a line from the input stream, into the array at charptr.
charptr may be any of three kinds of pointer: char*, unsigned char*, or
signed char*.

basic_string substr(size_type pos = 0, size_type n = npos) const
// ----------

std::string strInput = "!01020304";
char Exclamation = strInput[0];

std::istringstream strStream( strInput.substr(1, 2) );
unsigned short int A;
strStream >> A;
// etc.
// ----------
cout<<"Exclamation ="< cout<<"unsigned short int A ="< // -- output --
// Exclamation =!
// unsigned short int A =1

Does that help?
--
Bob R
POVrookie


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
mzdude
Guest





PostPosted: Sat Sep 24, 2005 8:23 pm    Post subject: Re: trouble converting a string to numbers using stringstrea Reply with quote

Sometimes the best C++ code is C.

Personally I would subscript through the string.

// code not tested

inline unsigned short AsciiToHexDigit( char ch )
{
if( ::isDigit(ch) )
return ch - '0';
return (ch - 'A') + 10;
}

// Usually caveats about testing the length of strInput
char exclamation = strInput[0];
unsigned short AA = AsciiToHexDigit(strInput[1]) * 0x10 +
AsciiToHexDigit(strInput[2]);



It ain't elegant, but it will be fast and as robust as anything else.

If you want to get C++ into the act you could always templatize the
AsciiToHexDigit(). Or make it twice as fast by making a single call to
AsciiToHexByte( char *chPtr ) with the assumption that 2 character
bytes are valid.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Angelo
Guest





PostPosted: Mon Sep 26, 2005 1:41 am    Post subject: Re: trouble converting a string to numbers using stringstrea Reply with quote

Thank you for replying, all them have been helpful.

Here's what I've come up with:

#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>

int main()
{
unsigned int A;
unsigned int B;
std::string strInput = "!B1ABA2A5";
std::istringstream strStream( strInput.substr(1,2) );

strStream >> std::setbase(16) >> A;
strStream.str( strInput.substr(3,2) );
strStream >> std::setbase(16) >> B;

std::cout << "value of the A: " << std::setbase(16) << A << "n";
std::cout << "value of B: " << std::setbase(16) << B << std::endl;

return 1;
}

It works for A, but not for B (B yields a value of 0). Is it invalid
to set strStream.str with another substring like Im trying to do here?


btw -- Im currently using g++in the newest cygwin build.

Thanks
Angelo


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
BobR
Guest





PostPosted: Tue Sep 27, 2005 8:22 am    Post subject: Re: trouble converting a string to numbers using stringstrea Reply with quote


Angelo wrote in message
<1127682727.887349.291620 (AT) g49g2000cwa (DOT) googlegroups.com>...
Quote:
Thank you for replying, all them have been helpful.
Here's what I've come up with:

Extremely close to what I tried.

Quote:

#include <string
#include #include #include
int main(){
unsigned int A;
unsigned int B;
std::string strInput = "!B1ABA2A5";
std::istringstream strStream( strInput.substr(1,2) );
strStream >> std::setbase(16) >> A;

// try this, worked for me.

strStream.clear();

// stream only had 2 chars in it, read them both,
// so, stream was at EOF (I think). 'clear()' resets fail-state.


Quote:
strStream.str( strInput.substr(3,2) );
strStream >> std::setbase(16) >> B;

std::cout << "value of the A: " << std::setbase(16) << A << "n";
std::cout << "value of B: " << std::setbase(16) << B << std::endl;

return 1;
}

It works for A, but not for B (B yields a value of 0). Is it invalid
to set strStream.str with another substring like Im trying to do here?

btw -- Im currently using g++in the newest cygwin build.

I tested with GCC 3.3.1 ( MinGW ).

--
Bob R
POVrookie


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
kanze
Guest





PostPosted: Tue Sep 27, 2005 8:29 am    Post subject: Re: trouble converting a string to numbers using stringstrea Reply with quote

Angelo wrote:
Quote:
I have a string which I need to convert to integers. I was
thinking that stringstreams would be the best way to convert
them, but I am having trouble. Here's a simple example:

#include <sstream

int main()
{
// string format: !AATTCCFF
// '!' just need to convert this to a char
// AA, TT, CC, FF are 2-byte unsigned hex (00-FF)
std::string strInput = "!01020304";
std::istringstream strStream( strInput );

unsigned short int A,T,C,F;
char Exclamation;

// I know this is not correct
strStream >> Exclamation >> A >> T >> C >> F;

return 0;
}

I couldnt find any examples on the web using stringstreams
that are similar to this. Somehow, I need to place 1-char
into Exclamation, and then use the next 2 for A, 2 for T, 2
for C, and 2 for F.

Am I simply using the wrong construct here? If not, could
somebody suggest how to accomplish this?

For some strange reason, the standard says that the width
attribute is ignored when parsing numbers. (Note that this was
not the case with scanf!). The canonical solution is to extract
the substring, and use istringstream on it. Alternatively, you
can just use sscanf on strInput.c_str(); while the scanf family
is one that I generally avoid, there are cases, like this, where
it remains the an appropriate solution -- not necessarily a good
solution, but perhaps better than the alternatives.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
John Potter
Guest





PostPosted: Tue Sep 27, 2005 11:22 am    Post subject: Re: trouble converting a string to numbers using stringstrea Reply with quote

On 25 Sep 2005 21:41:13 -0400, "Angelo" <kereszte (AT) msu (DOT) edu> wrote:

Quote:
unsigned int A;
unsigned int B;
std::string strInput = "!B1ABA2A5";
std::istringstream strStream( strInput.substr(1,2) );

strStream >> std::setbase(16) >> A;

This sets eof on the stream which causes further reads to fail.

strStream.clear();

Quote:
strStream.str( strInput.substr(3,2) );
strStream >> std::setbase(16) >> B;

John

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Tony Delroy
Guest





PostPosted: Tue Sep 27, 2005 11:28 am    Post subject: Re: trouble converting a string to numbers using stringstrea Reply with quote

Hi Angelo,

You can fix this...

Quote:
strStream.str( strInput.substr(3,2) );
strStream >> std::setbase(16) >> B;

.... by inserting "strStream.seekg(0);" to reposition yourself to the
start of the new stream content.

More generally, consider doing it C-style...

if (sscanf("!B1ABA2A5", "%c%2x%2x%2x%2x",
&exclamation, &a, &t, &c, &f) == 5)
{
i_am_so_happy();
}

Cheers,

Tony


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Maxim Yegorushkin
Guest





PostPosted: Tue Sep 27, 2005 2:32 pm    Post subject: Re: trouble converting a string to numbers using stringstrea Reply with quote


Angelo wrote:
Quote:
I have a string which I need to convert to integers. I was thinking
that stringstreams would be the best way to convert them, but I am
having trouble. Here's a simple example:

#include <sstream

int main()
{
// string format: !AATTCCFF
// '!' just need to convert this to a char
// AA, TT, CC, FF are 2-byte unsigned hex (00-FF)
std::string strInput = "!01020304";
std::istringstream strStream( strInput );

unsigned short int A,T,C,F;
char Exclamation;

// I know this is not correct
strStream >> Exclamation >> A >> T >> C >> F;

return 0;
}

I couldnt find any examples on the web using stringstreams that are
similar to this. Somehow, I need to place 1-char into Exclamation, and
then use the next 2 for A, 2 for T, 2 for C, and 2 for F.

Am I simply using the wrong construct here?

Yes, you are. Standard streams are useless for parsing.

Quote:
If not, could somebody suggest how to accomplish this?

Use sscanf.

unsigned short int A,T,C,F;
char Exclamation;
int r = sscanf("!01020304", "%c%2hx%2hx%2hx%2hx", &Exclamation, &A, &T,
&C, &F);
if(5 == r)
// parsed okay
else
// bad input string


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Carl Barron
Guest





PostPosted: Tue Sep 27, 2005 3:06 pm    Post subject: Re: trouble converting a string to numbers using stringstrea Reply with quote

In article <44LZe.316660$5N3.33257 (AT) bgtnsc05-news (DOT) ops.worldnet.att.net>,
BobR <RemoveBadBobR (AT) worldnet (DOT) att.net> wrote:

Quote:
Angelo wrote in message
[email]1127682727.887349.291620 (AT) g49g2000cwa (DOT) googlegroups.com[/email]>...
Thank you for replying, all them have been helpful.
Here's what I've come up with:

Extremely close to what I tried.


#include <string
#include #include #include
int main(){
unsigned int A;
unsigned int B;
std::string strInput = "!B1ABA2A5";
std::istringstream strStream( strInput.substr(1,2) );
strStream >> std::setbase(16) >> A;

// try this, worked for me.

strStream.clear();

// stream only had 2 chars in it, read them both,
// so, stream was at EOF (I think). 'clear()' resets fail-state.


strStream.str( strInput.substr(3,2) );
strStream >> std::setbase(16) >> B;

std::cout << "value of the A: " << std::setbase(16) << A << "n";
std::cout << "value of B: " << std::setbase(16) << B << std::endl;

return 1;
}

It works for A, but not for B (B yields a value of 0). Is it invalid
to set strStream.str with another substring like Im trying to do here?

btw -- Im currently using g++in the newest cygwin build.

I tested with GCC 3.3.1 ( MinGW ).

All you need to do is write the chars of the given string

into a stringstream inserting white space between the fields.
then one read of the the stringstream produces the results.
The format is fixed and the data must be copied so why not
do it all at once
void load_stream(std::iostream &strm,std::string const &str);
{
std::string::const_iterator in(str.begin();
std::ostreambuf_iterator *out = *in;
*++out = 't';
for(int i =0;i!=4;++i)
{
*++out = *++in;
*++out = *++in;
*++out = 't';
}
strm.seekg(0);
};

now it can be read with one line as originally desired.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Angelo
Guest





PostPosted: Tue Sep 27, 2005 3:36 pm    Post subject: Re: trouble converting a string to numbers using stringstrea Reply with quote

that fixed it. many thanks to everybody !


Quick question: should I have just used sscanf? Lately, I have been
trying to erase my old C habits when writing a C++ program.

Is the best mindset something like: "use C++ most of the time, and use
C when it is more convenient"?

Thanks all for the help
Angelo


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Dietmar Kuehl
Guest





PostPosted: Wed Sep 28, 2005 8:16 am    Post subject: Re: trouble converting a string to numbers using stringstrea Reply with quote

Tony Delroy wrote:
Quote:
More generally, consider doing it C-style...

if (sscanf("!B1ABA2A5", "%c%2x%2x%2x%2x",
&exclamation, &a, &t, &c, &f) == 5)
{
i_am_so_happy();
}

After considering the C-style, you would, of course, reject it:
assuming 'a', 't', 'c', and 'f' corresponding to the variables
'A', 'T', 'C', and 'F', respectively, of the original article,
the above code has undefined behavior: the type of the variables
shall be 'unsigned int' but the variable where declared to be
'unsigned short'. You would need the format specifier '%2hx' to
avoid this problem.

In general, use of IOStreams is much less subtle than using C's
format specifiers. I have found many errors due to wrong use of
these specifiers even in production code. Of course, this
information does not help you with the original problem of how
to extract pairs of (hexadecimal) digits from a string without
spaces.

My personal approach to this would revolve around a filtering
stream buffer which injects spaces at strategic points. How I
would implement such a filter would somewhat depend on the size
of file I need to read: for huge files I would use some buffering
strategy while for smaller files (i.e. "only" a few dozens MBs)
I would use a simple strategy:

class limitbuf:
public std::streambuf
{
public:
limitbuf(std::streambuf* sbuf): m_sbuf(sbuf), m_count(-1) {}
void set_count(int c) { m_count = c; }
int underflow()
{
int rc = this->m_count-- == 0
? traits_type::to_int_type(' ')
:this->m_sbuf->sbumpc();
if (rc != traits_type::eof())
{
this->m_char = traits_type::to_char_type(rc);
setg(&this->m_char, &this->m_char, &this->m_char + 1);
}
return rc;
}
std::streambuf* sbuf() { return m_sbuf; }

private:
std::streambuf* m_sbuf;
int m_count;
char m_char;
};

struct limit
{
limit(int c): m_count(c) {}
int m_count;
};

void limitbuf_deleter(std::ios_base::event ev,
std::ios_base& ib, int index)
{
if (ev == std::ios_base::erase_event)
delete static_cast<limitbuf*>(ib.pword(index));
}


std::istream& operator>> (std::istream& in, limit const& l)
{
static int index = std::ios_base::xalloc();

if (!dynamic_cast<limitbuf*>(in.rdbuf()))
{
limitbuf* buf = new limitbuf(in.rdbuf());
in.rdbuf(buf);
in.pword(index) = buf;
in.register_callback(limitbuf_deleter, index);
}
dynamic_cast<limitbuf*>(in.rdbuf())->set_count(l.m_count);
return in;
}

int main()
{
char f;
unsigned int a = 0, b = 0, c = 0, d = 0;

std::istringstream in("a01020304");
in >> f >> limit(2) >> a >> limit(2) >> b
Quote:
limit(2) >> c >> limit(2) >> d;
std::cout << "a: " << a << " b: " << b

<< "c: " << c << " d: " << d << "n";
}
--
<http://www.eai-systems.com> - Efficient Artificial Intelligence

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
BobR
Guest





PostPosted: Wed Sep 28, 2005 10:00 am    Post subject: Re: trouble converting a string to numbers using stringstrea Reply with quote


Angelo wrote in message
<1127829211.570758.98060 (AT) z14g2000cwz (DOT) googlegroups.com>...
Quote:
that fixed it. many thanks to everybody !

Quick question: should I have just used sscanf? Lately, I have been
trying to erase my old C habits when writing a C++ program.

Is the best mindset something like: "use C++ most of the time, and use
C when it is more convenient"?

Thanks all for the help
Angelo

Replace "convenient" with "practical" above, and I'll be more likely to
accept the statement.

I look at 'C' and 'C++' as a big toolbox. What tool you use depends on the
problem at hand. If there was only one practical solution to your original
post, all of the replies would have been very close to the same. As you can
see, you got several good solutions to the problem. Only experience will
help you to choose which one is best for a certain problem.
If your boss is yelling at you, then "git 'er done". If you are a student
(in school or a hobbyist), then try lots of different things, experiment.

What I posted was a "git 'er done" type thing. You will want to put it all
in a class method/function, add some checks for safety (try-catch), checks
for data validity, etc.. If you had to process the full content of a 120Gig
HardDrive vs. a single short string, my method would fail big time.

--
Bob R
POVrookie


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.