Display Negative Number

I am getting strings from an HTTP request that will have hex values and I must convert those strings to a signed decimal.

1
2
3
4
5
6
7
8
//typical string inside response: //0E1D052BFBB711C1002C0042007A014DFE44022B270F7FFF8000000000000000
//every 4 characters above are a signed decimal value

for (a = 0; a <= 63; a+=4){
	sprintf(vval,"0X%c%c%c%c",response[a],response[a+1],response[a+2],response[a+3]);
	ds = strtol(vval, NULL, 16);
	sprintf(vval,"%d",ds);
}


The problem is I never see a negative number. Decoding 0x8000 gives me 32768 but not -32768.

Thanks.
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <cstring>
#include <string>
#include <cstdint>
#include <sstream>
#include <vector>

int main()
{
    const char* const typical_response = "0E1D" "052B" "FBB7" "11C1" "002C" "0042"
                "007A" "014D" "FE44" "022B" "270F" "7FFF" "8000" "0000" "00g0" "0000" ;

    constexpr std::size_t RESP_SZ = 64 ;
    char response[RESP_SZ] ;
    std::memcpy( response, typical_response, RESP_SZ ) ;

    std::vector<int> numbers ;

    // every 4 characters above are a signed decimal value
    constexpr std::size_t NCHARS = 4 ;
    for( std::size_t i = 0 ; i < RESP_SZ ; i += NCHARS ) // in 4 char chunks
    {
        std::istringstream stm( { response+i, response+i+NCHARS } ) ;

        using uint_type = std::uint16_t ;
        using sint_type = std::int16_t ;
        uint_type value ; // read in as unsigned [ 0,  0xffff ]
        if( stm >> std::hex >> value && stm.eof() ) 
            numbers.push_back( sint_type(value) ) ; // push_back as signed [ -32768, +32767 ]
        else 
        {
            std::cerr << "inalid hex number starting at position " << i << ": '" << stm.str() << "'\n" ;
            numbers.push_back(0) ;
        }
    }

    for( int n : numbers ) std::cout << n << ' ' ;
    std::cout << '\n' ;
}

http://coliru.stacked-crooked.com/a/61d357c0fe036d20
Last edited on
You didn't give us the type of vval. My guess is vval is an int with a size of 4 bytes.

The value 0x8000 is only 2 bytes (4 hex characters = 2 bytes).

If you make vval a signed 2-byte value (short on some systems), you will probably get the behavior you are looking for.
0x8000 short is negative but 0x00008000 long is positive number.
You need to have 0xFFFF8000 to see it as negative. So as doug4 wrote: make vval short or sign extend short to 4 bytes:
vval = (vval<<16)>>16;
before using it in strtol
Thanks doug4, short worked.
Now I am trying to get 4 bytes into a floating point number. I am casting to float and can display positive numbers but negative numbers show 1.#R...

1
2
3
4
5
sprintf(vval,"0x%c%c%c%c%c%c%c%c",response[a+4],response[a+5],response[a+6],response[a+7],response[a],response[a+1],response[a+2],response[a+3]);
	dsl = strtol(vval, NULL, 16);
	printf("%d,%f\n",a, *(float *)&dsl);
	dsF = *(float *)&dsl;
	sprintf(fval,"%7.2f",dsF);


Thanks.
Last edited on
Here is the real problem, I did this little test:

1
2
3
4
5
long dsl;
char vval[16];

sprintf(vval,"0xbdcccccd");
dsl = strtol(vval, NULL, 16);

above, vval = "0xbdcccccd"
dsl = 0x7fffffff

got it.

unsigned int and strtoul fixed it.
Topic archived. No new replies allowed.