How do you convert char numbers to decimal and back or convert ASCII 'A'-'Z'/'a'-'z' to letter offsets 0 for 'A'/'a' …?

后端 未结 4 976
无人共我
无人共我 2020-12-07 05:20

If you have a char that is in the range \'0\' to \'9\' how do you convert it to int values of 0 to 9

And then how do you convert it back?

Also given letters

4条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-12-07 05:35

    There are two main ways to do this conversion: Lookup and Mathmatically

    All ASCII values are denoted in decimal notion in this answer

    Note that in ASCII: '0' is 48, 'A' is 65, and 'a' is 97

    Lookup:

    In the lookup version you have an array of char, and then place the mapped values in the array, and create an array of ints to convert back:

    In order to both validate and get the corresponding value when mapping char to int:

    0 will be a sentinal value to mean not mapped: out of range    
    all results will be one more than expected
    

    unsigned char is used to make sure a signed negative char is handled correctly

    While 'C' allows the notation { ['A'] = 1, ['B'] = 2,… }; , C++ does not, so generically the following code can be used to fill lookup tables:

    void fill_lookups(unsigned char * from_table, int from_size, int * to_table)
    {
         for (int i = 0; i < from_size; ++i)
         {
             to_table[from_table[i]]=i+1; // add one to support 0 as "out of range"
         }
    }
    
    unsigned char int_to_char[]={ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
    unsigned char int_to_lower[]={'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
                         'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
                         'u', 'v', 'w', 'x', 'y', 'z'};
    unsigned char int_to_upper[]={'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
                         'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
                         'U', 'V', 'W', 'X', 'Y', 'Z'};
    
    int char_to_int[UCHAR_MAX+2] = {};       // This will return 0 for non digits
    int letter_to_offset[UCHAR_MAX+2] = {};  // This will return 0 for non alpha
    
    fill_lookups(int_to_char, sizeof(int_to_char), char_to_int);
    fill_lookups(int_to_lower, sizeof(int_to_lower), letter_to_offset);
    fill_lookups(int_to_upper, sizeof(int_to_upper), letter_to_offset);
    
    // Helper function to check in range and always reduce in range lookups by 1
    int to_int(int * table, unsigned char c, bool * in_range)
    {
       int ret = table[c];
       if (ret)
       {
           *in_range=(1==1); // for C/C++ true
           --ret;
       }
       else
       {
           *in_range=(0==1); // for C/C++ false
       }
    
       return ret;
    }
    
    bool in_range;  // always true in these cases
    int a=to_int(char_to_int, '7', &in_range); // a is now 7
    char b=int_to_char[7]; // b is now '7'    
    int c=to_int(letter_to_offset, 'C', &in_range); // c=2
    int d=to_int(letter_to_offset, 'c', &in_range); // d=2
    char e=int_to_upper[2]; // e='C'
    char f=int_to_lower[2]; // f='c'
    

    While this will work and if validation or other lookups are needed this might make sense, but...

    In general a better way to do this is using mathmatic equations.

    Mathmatically (alpha works for ASCII)

    Assuming that the conversions have already been validated to be in the correct range: (C style cast used for use with C or C++)

    Note that '0'-'9' are guarenteed to be consecutive in C and C++

    For ASCII 'A-Z' and 'a-z' are not only consecutive but 'A' % 32 and 'a' % 32 are both 1

    int a='7'-'0';         // a is now 7 in ASCII: 55-48=7
    
    char b=(char)7+'0';    // b is now '7' in ASCII: 7 + 48
    
    int c='C' % 32 - 1;    // c is now 2 in ASCII : 67 % 32 = 3 - 1 = 2
    

    -or- where we know it is uppercase

    int c='C'-'A';         // c is now 2 in ASCII : 67 - 65 = 2
    
    
    int d='c' % 32 - 1;    // d is now 2 in ASCII : 99 % 32 = 3 - 1 = 2
    

    -or- where we know it is lowercase

    int d='c'-'a';         // d is now 2 in ASCII : 99 - 97 = 2
    
    char e=(char)2 + 'A';  // e is 'C' in ASCII : 65 + 2 = 67
    char f=(char)2 + 'a';  // f is 'c' in ASCII : 97 + 2 = 99
    

提交回复
热议问题