C/C++: Converting hexadecimal value in char to integer

前端 未结 7 1621
萌比男神i
萌比男神i 2021-01-01 06:28

I have hexadecimal values stored as characters:

char A = \'0\';
char B = \'6\';
char C = \'E\';

... I need them coverted to integers. I kno

相关标签:
7条回答
  • 2021-01-01 06:30
    int v = (A > '9')? (A &~ 0x20) - 'A' + 10: (A - '0');
    

    is correct for ASCII. For other character sets, a similar approach would work, but you would then want toupper instead of &~ 0x20.

    0 讨论(0)
  • 2021-01-01 06:31

    You could try strtol. But strtol needs a 0 terminated char *, so:

    long x = strtol((char[]){A, 0}, NULL, 16);
    
    0 讨论(0)
  • 2021-01-01 06:34
    #include <stdio.h>
    #include <stdlib.h>
    
    
    int xtoi(char c)
    {
        int v = -1;
        char w=toupper(c);
        if(w >= 'A' && w <= 'F'){
            v = w - 'A' + 0x0A;
        }else if (w >= '0' && w <= '9'){
            v = w - '0';
        }
    
        return v;
    }
    
    int main(int argc,char **argv)
    {
        printf("v:%p\n",argc == 2 ? xtoi(argv[1][0]):-1);
        return 0;
    }
    
    0 讨论(0)
  • 2021-01-01 06:37

    You can explicity state you want to use base 16 with strtol

    char C = 'E';
    int num = strtol (&C ,NULL,16); // 14
    

    Beware that C is not a null terminated array, simply solved if you can change your characters to the following:

    char C[] = "E";
    int num = strtol(C, NULL, 16);
    
    0 讨论(0)
  • 2021-01-01 06:39

    In C:

    const char chrs[] = "0123456789ABCDEF";
    
    int value = -1; // sentinel
    const char *loc = strchr(chrs, ch);
    if (loc)
        value = loc - chrs;
    

    or, using C++:

    const std::string chrs("0123456789ABCDEF");
    int value = chrs.find(ch);
    
    0 讨论(0)
  • 2021-01-01 06:47

    The obvious solution is to make a one character string, and use the standard conversion techniques on it:

    std::istringstream tmp( std::string( 1, A ) );
    tmp >> anInt;
    

    It's a bit heavy, however (to put it lightly), and probably not very efficient in terms of runtime (a litote if I ever heard one).

    One simple and robust solution is a table lookup:

    static char const digits[] = "0123456789ABCDEF";
    int value = std::find(digits, digits + 16, A) - digits;
    if (value >= 16) {
        //  A wasn't a hex digit...
    }
    

    Alternatively (and much faster) is to use the character as an index into a table:

    static signed char const values[] =
    {
        -1, -1, -1, -1, -1, -1, -1, -1,     //  0x00-0x07
        //  ...
         0,  1,  2,  3,  4,  5,  6,  7,     //  0x30-0x37
         8,  9, -1, -1, -1, -1, -1, -1,     //  0x38-0x3F
        -1, 10, 11, 12, 13, 14, 15, -1,     //  0x40-0x47
        //  ...
        -1, 10, 11, 12, 13, 14, 15, -1,     //  0x60-0x67
        //  ...
    };
    
    
    int value = values[static_cast<unsigned char>( A )];
    

    Note that this is very dependent on the encoding; you might want to build it up at runtime from a list of digits, to avoid any encoding issues. Something like:

    struct ValueTable
    {
        signed char values[256];
        ValueTable()
        {
            std::fill( begin(values), end(values), -1 );
            static char const digits[] = "0123456789ABCDEF";
            for ( int i = 0; i < 16; ++ i ) {
                values[ digits[i] = i;
                values[ tolower( digits[i] ) ] = i;
            }
        }
    };
    static ValueTable const map;
    
    //   ...
    int value = map.values[ static_cast<unsigned char>( A ) ];
    
    0 讨论(0)
提交回复
热议问题