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

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

一、从高位到低位单个字符转换

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

main.c
#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。

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

二、从低位到高位单个字符转换

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

main.c
#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编译后,输入十六进制字符串数据进行测试,结果如下图所示:

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

评论

评论加载中…