 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Angelo Guest
|
Posted: Mon Oct 17, 2005 5:16 pm Post subject: trouble converting from string to signed int with istringstr |
|
|
I have a signed Hex value in a string that needs to be converted to a
signed int. Here's my code:
#include "stdafx.h"
#include <sstream>
#include <iostream>
int main(int argc, char* argv[])
{
long Val;
// -998 hex value, 2's compliment
std::string strVal = "FFFFFC1A";
std::istringstream strIn( strVal );
strIn >> std::hex >> Val;
if ( strIn.fail() )
std::cout << "conversion failedn";
else
std::cout << "converted value: " << static_cast
std::endl;
return 0;
}
if I use this code, I get conversion failed, however, if I change Val
from long to unsigned long, my output is -998 like I would expect. 2
questions here:
1. why does the conversion fail if Val is a signed long?
2. Is there any problems with using unsigned long for Val and casting
to signed long?
Note: Im using VC++6.0
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 |
|
 |
kanze Guest
|
Posted: Wed Oct 19, 2005 2:02 am Post subject: Re: trouble converting from string to signed int with istrin |
|
|
Angelo wrote:
| Quote: | I have a signed Hex value in a string that needs to be converted to a
signed int. Here's my code:
#include "stdafx.h"
#include <sstream
#include
int main(int argc, char* argv[])
{
long Val;
// -998 hex value, 2's compliment
std::string strVal = "FFFFFC1A";
|
That is: "4294966298" in decimal.
| Quote: | std::istringstream strIn( strVal );
strIn >> std::hex >> Val;
if ( strIn.fail() )
std::cout << "conversion failedn";
else
std::cout << "converted value: " << static_cast
std::endl;
return 0;
}
if I use this code, I get conversion failed, however, if I
change Val from long to unsigned long, my output is -998 like
I would expect. 2 questions here:
1. why does the conversion fail if Val is a signed long?
|
Because you have overflow. Technically, undefined behavior, but
any good implementation will simply fail. 0xFFFFFC1A is a
positive value, equal to 4294966298 in decimal. If long's are
only 32 bits on your machine, this value doesn't fit, so you
have overflow. -998 in hex would be -3E6.
There is some confusion here, I imagine, because you cannot in
fact output a long in hex format; for some strange reason, the
long will be converted into unsigned long, and output as an
unsigned long.
| Quote: | 2. Is there any problems with using unsigned long for Val and
casting to signed long?
|
Officially, yes. The value in the unsigned long is out of the
range of a long (supposing 32 bit long's), so the results are
implementation defined, and may cause program termination.
(Note that implementation defined means that a conforming
implementation is required to document what they do. If you
find such documentation, let us know -- I think it will be a
first.)
Practically, no. There are several classic cases where you more
or less have to -- assigning the results of istream::get() or
fgetc() to a char, for example, if char is signed. The result
is that almost all programs count on it, and any implementation
which didn't make it work as expected would break too much code
for the implementation to be viable. (Presumably, an
implementation could make a special case of converting an int to
a char, but I have never heard of an implementation which does
so.)
| Quote: | Note: Im using VC++6.0
|
You really should upgrade. VC++ was an excellent compiler when
it first came out, but that was a long, long time ago, and the
world has moved on since then.
--
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 |
|
 |
Angelo Guest
|
Posted: Thu Oct 20, 2005 11:14 am Post subject: Re: trouble converting from string to signed int with istrin |
|
|
try this:
#include <iostream>
int main()
{
long int mylong = 0xFFFFFC1A;
std::cout << "mylong: " << mylong << std::endl;
return 0;
}
if a long is 32bits then this will print out -998. 0xFFFFFC1A is -998
in binary 2's complement format, I dont beleive it's represented as
-3E6 internally. if you change the long int to an unsigned long int
then it will output as 4294966298.
I think this is correct but please correct me if I'm wrong.
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 |
|
 |
Angelo Guest
|
Posted: Thu Oct 20, 2005 12:12 pm Post subject: Re: trouble converting from string to signed int with istrin |
|
|
Also, I agree that we need to upgrade vc++ I beleive that we will
be upgrading vc++ soon. All of our software depends on mfc, is it even
possible to use a different compiler for that?
At home, I use g++ with eclipse and it seems to run pretty well. Being
free is a bonus.
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 |
|
 |
kanze Guest
|
Posted: Fri Oct 21, 2005 4:27 pm Post subject: Re: trouble converting from string to signed int with istrin |
|
|
Angelo wrote:
| Quote: | try this:
#include
int main()
{
long int mylong = 0xFFFFFC1A;
std::cout << "mylong: " << mylong << std::endl;
return 0;
}
if a long is 32bits then this will print out -998.
|
Technically, you have implementation defined behavior, which may
in fact trap. The value of 0xFFFFFC1A is 4294966298. If long
is only 32 bits, it doesn't fit, so the results of the
conversion are implementation defined.
In practice, you are probably right for most, if not all, two's
complement machines (and the only modern machine I know of which
isn't two's complement has 36 bit longs).
| Quote: | 0xFFFFFC1A is -998
|
No. At least, not in any math I know of. 0xFFFFFC1A is
4294966298.
The results of converting the unsigned long with the value
4294966298 to a long may be -998, but that's the result of an
implementation defined conversion, which changes the value.
| Quote: | in binary 2's complement format, I dont beleive it's
represented as -3E6 internally.
|
I'm not sure what that means. On my Sparc, in 32 bit mode, the
internal representation does have the sign bit set, which means
that the value is negative. And the definition of the
representation of negative values says that when all of the bits
are taken together, the value is -998. Or -0x36E, if you
prefer.
If you are talking about the bit pattern, then the bit pattern
used to represent -998 is 11111111111111111111110000011010. In
C++, you can access the bit pattern using the & operator and
masks, but it really isn't relevant to much of anything.
| Quote: | if you change the long int to an unsigned long int then it
will output as 4294966298.
I think this is correct but please correct me if I'm wrong.
|
It's the usual implementation defined behavior on a 32 bit
machine. But the fact remains that it is the result of
implementation defined conversions.
The original problem is due to the fact that the C++ standard
defines all hexidecimal input and output as if taking place on
unsigned values. On output, it converts a long to unsigned
long. On input, it will read the value as an unsigned long,
then convert it to a signed long. With the caveat that if the
value is not representable, it is undefined behavior, not the
implementation defined conversion you get normally. Most
quality implementations will treat it as an error, and set
failbit.
And of course, the conversion of a negative signed long to
unsigned long on output results in a value that is not
representable as a long. So you get the error on input.
--
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 |
|
 |
Angelo Guest
|
Posted: Wed Oct 26, 2005 1:06 pm Post subject: Re: trouble converting from string to signed int with istrin |
|
|
Ohhhh, I think I understand now. I thought that a negative number
could be represented via hex in c++ (via 2's complement, not using a
'-' sign).
So, in c++, there is no guarantee that assigning a signed long to
0xFFFFFC1A would come up with -998(base10).
Question: If I assigned a signed long with
11111111111111111111110000011010(base2), is there any guarantee that
it'll come out with -998 base10 for 32 bit longs?
Thanks 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 |
|
 |
Angelo Guest
|
Posted: Wed Oct 26, 2005 11:09 pm Post subject: Re: trouble converting from string to signed int with istrin |
|
|
Also, just so you know that my problem isnt contrived, I am trying to
do this for a project. I have a serial temp sensor which returns the
temperatures as a 32 bit signed value(negatives in 2's compliment), but
the values are given in base 16.
So if it returns something like FFFFFC1A, then I am supposed to
interpret it as -998. I am trying to figure out an error free way to
convert this string into a signed long.
Angelo
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Wed Oct 26, 2005 11:13 pm Post subject: Re: trouble converting from string to signed int with istrin |
|
|
In article <1130277523.046616.125840 (AT) o13g2000cwo (DOT) googlegroups.com>,
Angelo <kereszte (AT) msu (DOT) edu> writes
| Quote: | Ohhhh, I think I understand now. I thought that a negative number
could be represented via hex in c++ (via 2's complement, not using a
'-' sign).
So, in c++, there is no guarantee that assigning a signed long to
0xFFFFFC1A would come up with -998(base10).
Question: If I assigned a signed long with
11111111111111111111110000011010(base2), is there any guarantee that
it'll come out with -998 base10 for 32 bit longs?
|
You are assuming that negative numbers are necessarily represented using
2's complement. The C++ Standard (as does the C Standard) allows the use
of 1's complement as well as sign and magnitude. Most current systems
use 2's complement but that is not required.
So in answer to your final question, the C++ Standard does not guarantee
that the bit pattern quoted represent -998.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Valentin Samko Guest
|
Posted: Wed Oct 26, 2005 11:16 pm Post subject: Re: trouble converting from string to signed int with istrin |
|
|
Angelo wrote:
| Quote: | Also, I agree that we need to upgrade vc++ I beleive that we will
be upgrading vc++ soon. All of our software depends on mfc, is it even
possible to use a different compiler for that?
|
Just upgrade to VC7.1. It is just that VC6 is pre standard and buggy (compared the modern
compilers). For example, in some cases it does not call destructors for temporary objects
on the stack. And there are plenty of compile time problems.
--
Valentin Samko - http://val.samko.info
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Thu Oct 27, 2005 1:11 pm Post subject: Re: trouble converting from string to signed int with istrin |
|
|
In article <1130335267.739246.22200 (AT) o13g2000cwo (DOT) googlegroups.com>,
Angelo <kereszte (AT) msu (DOT) edu> writes
| Quote: | Also, just so you know that my problem isnt contrived, I am trying to
do this for a project. I have a serial temp sensor which returns the
temperatures as a 32 bit signed value(negatives in 2's compliment), but
the values are given in base 16.
So if it returns something like FFFFFC1A, then I am supposed to
interpret it as -998. I am trying to figure out an error free way to
convert this string into a signed long.
|
Why didn't you ask the question to start with instead of worrying about
representations.
1) Check your implementation uses 2's complement (it probably does)
2) Use std::strol() from <cstdlib>
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[ 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
|
Posted: Fri Oct 28, 2005 8:29 am Post subject: Re: trouble converting from string to signed int with istrin |
|
|
Francis Glassborow wrote:
| Quote: | In article
[email]1130335267.739246.22200 (AT) o13g2000cwo (DOT) googlegroups.com[/email]>, Angelo
[email]kereszte (AT) msu (DOT) edu[/email]> writes
Also, just so you know that my problem isnt contrived, I am
trying to do this for a project. I have a serial temp sensor
which returns the temperatures as a 32 bit signed
value(negatives in 2's compliment), but the values are given
in base 16.
So if it returns something like FFFFFC1A, then I am supposed
to interpret it as -998. I am trying to figure out an error
free way to convert this string into a signed long.
Why didn't you ask the question to start with instead of
worrying about representations.
|
Well, his problem is one of representation. (Supposing that the
FFFFFC1A is text.)
| Quote: | 1) Check your implementation uses 2's complement (it probably does)
2) Use std::strol() from <cstdlib
|
According to the C standard, if the correct value is outside the
range of representable values, LONG_MIN or LONG_MAX will be
returned, according to the sign of the value. Any way you cut
it, the correct value of the string FFFFFC1A is 4294966298. If
longs are 32 bits on his machine, stdtol should return
2147483648 (and store ERANGE in errno); if they are longer,
strtol should return 4294966298. The only way strtol can return
a negative value is if it is given a negative value to convert.
The problem is that his data source converts negative values to
the equivalent unsigned value, and outputs that as a string. If
(as is highly likely), his machine and that data source use the
same format, and his machine makes conversions along the lines
unsigned->int->unsigned an identity function, then the correct
solution is to read the value in as an unsigned long, and then
convert the unsigned long to long.
If this doesn't work, he has a bit more work on his hands, but I
would still start by getting the value that was output, as an
unsigned long.
--
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 |
|
 |
kanze Guest
|
Posted: Fri Oct 28, 2005 8:31 am Post subject: Re: trouble converting from string to signed int with istrin |
|
|
Angelo wrote:
| Quote: | Ohhhh, I think I understand now. I thought that a negative
number could be represented via hex in c++ (via 2's
complement, not using a '-' sign).
|
Attention: don't confuse external representation (in text
format) with internal.
| Quote: | So, in c++, there is no guarantee that assigning a signed long
to 0xFFFFFC1A would come up with -998(base10).
|
No. On my machine (in 64 bit mode), it doesn't. More
generally, conversions of signed to unsigned are well defined,
but only for a given length (and the length of long may be
anything greater than or equal to 32 -- as a minimum, 32, 36, 48
and 64 have existed), conversions in the other direction are
"implementation defined".
In practice, assigning an unsigned long which has the value
0xFFFFFC1A to a long will result in -998 on most modern machines
where long is 32 bits. But you've got to get that unsigned long
first; a text string is NOT an unsigned long, and the standard
speaks of what happens when the correctly converted value is not
representable. The correctly converted value is only negative
if there is a - sign.
| Quote: | Question: If I assigned a signed long with
11111111111111111111110000011010(base2), is there any
guarantee that it'll come out with -998 base10 for 32 bit
longs?
|
Not from the standard. Probably from your implementation
(again, supposing 32 bit longs).
If you have control of both sides, pass the value as a decimal
value. It's a lot simpler, and more robust. (But one might
legitimately ask why C++ doesn't allow outputting signed values
as hexadecimal.)
--
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 |
|
 |
Angelo Guest
|
Posted: Wed Nov 09, 2005 1:51 am Post subject: Re: trouble converting from string to signed int with istrin |
|
|
Very interessting! I must check the output of the temp sensor and see
if it supports outputing in regular decimal format.
why doesnt c++ allow outputting signed values as hex?
Thanks for all your help. It's definitely helped me, and I have
learned quite a bit.
Angelo
[ 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
|
Posted: Wed Nov 09, 2005 2:25 pm Post subject: Re: trouble converting from string to signed int with istrin |
|
|
Angelo wrote:
[...]
| Quote: | why doesnt c++ allow outputting signed values as hex?
|
Good question. A simple answer for the standard streams would
be that formatted output is defined in terms of C's printf
format specifiers, and there isn't a format specifier for hex
for signed int's. (Remember that a printf format specifier must
also indicate the type -- there is a different format specifier
for decimal signed int and decimal unsigned int, and it is the
format specifier, and not the actual type passed, that
determines how the value is interpreted.)
But that's just part of it. I just checked, and the classical
iostream's didn't support it either.
I suspect that the main reason is simply that most of the time,
when you output in hex format, it's because you want to see the
bit pattern, and signedness is irrelevant. It probably never
occurred to anyone that you *are* outputting a value, not just a
bit pattern, and that someone might want to read the value back
in "as a value". But I'm really just guessing about it.
--
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 |
|
 |
|
|
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
|
|