TypeCodes

视角:C语言将十六进制字符串转成十进制整数

在前文《再议C语言将十六进制字符串转成十进制整数》@大致 童鞋帮忙提了一个思路:直接将指针p读取的十六进制字符串中的单个字符转换后的结果保存在iResult中,而不是保存在指针p指向的内存中。这样思路更为简洁,下面是具体的两个实现程序。

1 从高位到低位单个字符转换

正向转换时,提前判断出字符串中部分非法字符,然后根据+-0x0X这四个特殊字符(串)对指针变量p进行特殊处理。

 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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <stdio.h>
#include <string.h>

/**
 * @FileName  HexStr2Integer.c
 * @author    vfhky 2015.05.30 https://typecodes.com/cseries/simplifychexstrtoint.html
 * @param     [in]HexStr 十六进制字符串(例如"eE2"、"Fa1"、"2011"、"-eE2"、"+eE2"等) 
 * @return    -1:字符串为空; -2:字符串中包含非十六进制的字符; 其它:转换后的十进制整数
 */
int HexStr2Integer( char * HexStr )
{
    int iResult = 0, iFlag = 1;

    //判断字符串是否合法
    if( NULL == HexStr || ( *HexStr == '+' && *(HexStr+1) == '\0' ) || ( *HexStr == '-' && *(HexStr+1) == '\0' ) 
        || ( *HexStr == 0x30 && *(HexStr+1) == 0x58 && *(HexStr+2) == '\0' )
        || ( *HexStr == 0x30 && *(HexStr+1) == 0x78 && *(HexStr+2) == '\0' ) )
    {
        return -1;
    }

    //指针变量p指向字符串的首位
    char * p = HexStr;

    //对以"+"、"-"号开头的十六进制字符串的处理
    if ( '-' == *p || '+' == *p )
    {
        if( *p == '-' )
            iFlag = -1;
        ++p;
    }
    //对"0x"或者"0X"开头的十六进制字符的处理
    else if( ( *p == 0x30 && *(p+1) == 0x58 ) || ( *p == 0x30 && *(p+1) == 0x78 ) )
    {
        p += 2;
    }

    while( *p != '\0' )
    {
        if ( *p >= 48 && *p <= 57 )
            iResult = ( *p - 48 )+ ( iResult<<4 );
        else if ( *p >= 65 && *p <= 70 )
            iResult = ( *p - 65 + 10 )+ ( iResult<<4 );
        else if ( *p >= 97 && *p <= 102 )
            iResult = ( *p - 97 + 10 )+ ( iResult<<4 );
        else
            return -2;

        ++p;
    }
    return iFlag*iResult;
}

int main( int argc, char * argv[] )
{
    char cHexString[200+1];
    while(1)
    {
        memset( cHexString, 0x00, sizeof(cHexString) );
        printf( "Please input a HexString with length less than 200:\n" );
        scanf( "%s", cHexString );
        printf( "---->[%d]\n", HexStr2Integer(cHexString) );
    }
    return 0;
}

同样使用GCC编译命令gcc HexStr2Integer.c -o HexStr2Integer,然后输入测试用的十六进制的字符串"eE2"、"Fa1"、"2011"、"-eE2"、"+eE2"分别转换成了对应的十进制整数:3810、4001、8209、-3810、3810。

十六进制字符串转成十进制整数

2 从低位到高位单个字符转换

逆向转换时,需要注意while循环中通过对+-0x0X这四个特殊字符(串)的判断出非法字符。

 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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <stdio.h>
#include <string.h>

/**
 * @FileName  HexStr2Integer2.c
 * @author    vfhky 2015.05.30 https://typecodes.com/cseries/simplifychexstrtoint.html
 * @param     [in]HexStr 十六进制字符串(例如"eE2"、"Fa1"、"2011"、"-eE2"、"+eE2"等) 
 * @return    -1:字符串为空; -2:字符串中包含非十六进制的字符; 其它:转换后的十进制整数
 */
int HexStr2Integer2( char * HexStr )
{
    int iResult = 0, iCycle = 1, iFlag = 1;

    //判断字符串是否合法
    if( !strlen( HexStr ) )
    {
        return -1;
    }

    //指针变量p指向字符串的末尾
    char * p = HexStr + strlen( HexStr );

    while( (--p+1) != HexStr )
    {
        if ( *p >= '0' && *p <= '9' )
            iResult += ( *p - '0' )*iCycle;
        else if ( *p >= 'A' && *p <= 'F' )
            iResult += ( *p - 'A' + 10 )*iCycle;
        else if ( *p >= 'a' && *p <= 'f' )
            iResult += ( *p - 'a' + 10 )*iCycle;
        else if ( ( '+' == *p && ( p == HexStr + 1 ) )
            || ( 'x' == *p && '0' == *( p - 1 ) && ( p == HexStr + 1 ) ) 
            || ( 'X' == *p && '0' == *( p - 1 ) && ( p == HexStr + 1 ) ) )
            break;
        else if ( '-' == *p && p == HexStr )
            iFlag = -1;
        else
            return -2;

        iCycle <<= 4;
    }
    return iFlag*iResult;
}

int main( int argc, char * argv[] )
{
    char cHexString[200+1];
    while(1)
    {
        memset( cHexString, 0x00, sizeof(cHexString) );
        printf( "Please input a HexString with length less than 200:\n" );
        scanf( "%s", cHexString );
        printf( "---->[%d]\n", HexStr2Integer2(cHexString) );
    }
    return 0;
}

同样,使用GCC编译后,输入十六进制字符串数据进行测试,结果如下图所示:

十六进制字符串转成十进制整数

打赏支持

Comments »