string to int problem (solved)

Dear All,

I have a string "stringA" looks like "FFFFFED4", which is -300 in HEX... I want to convert it into a int "A", then, using Serial. print(A) to give me "-300". I can add "0x" or "FFFF FFFF" in front of the string to make whichever converts easier.

I have tried "A = string.toInt()","stringA.toCharArray(A,20); signed int B = atoi(A)", and "int B = strtol(A,NULL,16)". None of them shows me the right number. I have got "0","-1","2147483647" and other numbers as the results.

I know I need learn more about data type. Could anybody give some suggestion about this problem?

Best regards,

bool parseHex ( char* s , int* x )
{
    int val=1 ;
    int v=0 ;
    char c = s[0] ;
    while ( digval( c, &v ))
    {
        val = val*16 + v ;
        c=*(++s) ;
    }
    *x = val ;
    return true ;
}


bool digval ( char c, int *v )
{
    if ( c >='0' && c <='9' ) { *v=c-'0' ; return true ; }
    else if ( c >= 'A' && c <='F' ) { *v = c-'A' ; return true ; }
    else return false ;
}

Something like this might work - not tested.

If you know there are always going to be exactly 8 chars, there are simpler ways.

Hello,

Try with strtoul

Thank you for your advice, michinyon.

michinyon:
If you know there are always going to be exactly 8 chars, there are simpler ways.

yes, there are always 8 chars in this string, because I selected them from a longer string by using "readString.substring".

Thank you for reply, guix.

guix:
Hello,

Try with strtoul

I tried strtoul. The char*A shows right result like "FFFFFED4", but int B is "-1"......

int32_t B = strtoul( "FFFFFED4", NULL, 16 );
Serial.println( B );

I've just tried and it prints -300 as expected.

A int is 2 bytes, and your string is 4 bytes. That is not your problem because -300 can be stored in 2 bytes, but you should really use the correct data type.

I suggest you post your code, you may have an error somewhere else :wink:

If you got -1, it was probably only reading the FFFF bit.

So, according to the OP, strtol( ) results in 2147483647

and according to reply#6, strtoul( ) results in -300

How bizarre

guix:

int32_t B = strtoul( "FFFFFED4", NULL, 16 );

Serial.println( B );




I've just tried and it prints -300 as expected.

A int is 2 bytes, and your string is 4 bytes. That is not your problem because -300 can be stored in 2 bytes, but you should really use the correct data type.

I suggest you post your code, you may have an error somewhere else ;)

Thank you...I used 0xFFFFFED4.
Your code is perfect. Thanks again.

michinyon:
So, according to the OP, strtol( ) results in 2147483647

and according to reply#6, strtoul( ) results in -300

How bizarre

I was wrong. The problem is solved.

Thank you very very much for the reply.

If you have control of how the data is sent, then maybe skip the hex representation of the number and use a numeric representation.

zoomkat:
If you have control of how the data is sent, then maybe skip the hex representation of the number and use a numeric representation.

Thank you very much for your reply. No, I cannot control the data. It is sent by another device.
Anyway, the problem has been solved, thanks again.

int32_t B = strtoul( "FFFFFED4", NULL, 16 );

The problem i have with this "perfect" solution, is that you are actually converting your hex string to an unsigned long number, and then relying on the correct invisible conversion that occurs when you assign a large unsigned value to a signed variable not large enough to contain it.

Now you probably can "rely" on that implicit conversion working because some standard says that's how it should work these days, but I'd rather not.

If it is a signed long that you are after ( and, if -300 is the "correct" answer, you are ), then I'd be looking to get strtol( ) working properly, because it should be able to.

I remember having problems with strtol, it seem to bug with bases other than 10..

guix:
I remember having problems with strtol, it seem to bug with bases other than 10..

More likely is that FFFFFED4 is too large to fit in a signed long. The range of a signed long is -80000000 to 7FFFFFFF. strtol is designed to return one of those extrema when the input string exceeds the range. strtoul happens to work because the value fits in an unsigned long, which when converted to a signed long becomes the value you expect.

More likely is that FFFFFED4 is too large to fit in a signed long.

That's silly. FFFFFED4 IS a signed long. It's -300. That's how 2's complement representation for integers works.

michinyon:
That's silly. FFFFFED4 IS a signed long. It's -300. That's how 2's complement representation for integers works.

I was referring to the value, not to the bit pattern, of FFFFFED416. It is equal to 429496699610. strtol tells you that the number is too big to fit in a long (because it really is too big) by returning LONG_MAX.

If you want -30010 in hexadecimal, that would be -12C16.

strtol and strtoul operate on strings containing values. They don't operate on strings containing bit patterns. In two's complement, the bit patterns 0x00000000 through 0x7FFFFFFF correspond to the same value, but the bit patterns 0x80000000 through 0xFFFFFFFF correspond to the values -0x80000000 through -0x00000001. Go ahead... try passing a negative number in hexadecimal to strtol, such as strtol("-0x12c", NULL, 0). It returns the correct answer (-300).