题目:
编写函数htoi(s),把由十六进制数字组成的字符串(包含可选的前缀0x或0X)转换为与之等价的整型值。字符串中允许包含的数字包括:0~9、a~f以及A~F。
自我解答:
编程思路:
首先函数定义为 int htoi(const char s[]),输入参数用const加以声明,防止在函数内部对其改动;其次返回值为int型,当输入字符串有效时,输出相应的转换值,有无效字符时返回-1并抛出异常;
#includeint htoi(const char s[]) { int i = 0; int hex = 0; bool skipHeader = false; while(s[i] != ' ') { if(!skipHeader && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) { skipHeader = true; if(s[2] == ' ') { printf("lack of digits after 0x or 0Xn"); hex = -1; break; } else { i = 2; continue; } } else { if(s[i] >= '0' && s[i] <= '9') { hex = hex * 16 + (s[i] - '0'); } else if(s[i] >= 'a' && s[i] <= 'f') { hex = hex * 16 + (s[i] - 'a' + 10); } else if(s[i] >= 'A' && s[i] <= 'F') { hex = hex * 16 + (s[i] - 'A' + 10); } else { printf("error: illegal input: %cn", s[i]); return -1; } i++; } } if(s[0] == ' ') { printf("no inputn"); hex = -1; } return hex; } int main() { printf("0x%xn", htoi("1234")); printf("0x%xn", htoi("0x1234")); printf("0x%xn", htoi("0")); printf("0x%xn", htoi("0x0")); printf("0x%xn", htoi("0x1234ab")); printf("0x%xn", htoi("0x1234AF")); printf("0x%xn", htoi("0x123456789")); printf("%dn", htoi("0x")); printf("%dn", htoi("0s")); printf("%dn", htoi("0x120xab")); printf("%dn", htoi("")); }
运行结果为:
0x1234 0x1234 0x0 0x0 0x1234ab 0x1234af 0x23456789 lack of digits after 0x or 0X -1 error: illegal input: s -1 error: illegal input: x -1 no input -1
程序中考虑了如下几种情况:
1. 有效数字包含除0~9 a~f A~F之外字符
2. 自动判断是否以0x或0X开头,以及0x或0X之后是否有数字
3. 空字符串的情况
未考虑数据超范围的情况,这种情况会自动截断
参考答案:
#include#define YES 1 #define NO 0 int htoi(char s[]) { int hexdigit, i, index, n; i = 0; if(s[i] == '0') { ++i; if(s[i] == 'x' || s[i] == 'X') ++i; } n = 0; index = YES; for(; index == YES; ++i) { if(s[i] >= '0' && s[i] <= '9') hexdigit = s[i] - '0'; else if(s[i] >= 'a' && s[i] <= 'f') hexdigit = s[i] - 'a' + 10; else if(s[i] >= 'A' && s[i] <= 'F') hexdigit = s[i] - 'A' + 10; else index = NO; if(index == YES) n = 16 * n + hexdigit; } return n; }
整个函数是由下面这条语句控制的:
for(; index == YES; ++i)
其中,整型变量i是数组s的下标。当s[i]是一个合法的十六进制数字时,index的取值将保持为YES,而循环也将继续进行。整形变量hexdigit的取值范围时0~15.
语句if(index == YES)保证数组元素s[i]是一个合法的十六进制数字字符,其值在hexdigit的范围之内。当循环结束时,函数htoi将返回变量n的值。
这个函数与atoi很相似(参见教材第35页)
补充:
用下面main函数对参考答案中的代码进行测试:
int main()
{
printf("0x%xn", htoi("1234"));
printf("0x%xn", htoi("0x1234"));
printf("0x%xn", htoi("0"));
printf("0x%xn", htoi("0x0"));
printf("0x%xn", htoi("0x1234ab"));
printf("0x%xn", htoi("0x1234AF"));
printf("0x%xn", htoi("0x123456789"));
printf("0x%xn", htoi("0x"));
printf("0x%xn", htoi("0s"));
printf("0x%xn", htoi("0x120xab"));
printf("0x%xn", htoi(""));
}
输出结果为:
0x1234
0x1234
0x0
0x0
0x1234ab
0x1234af
0x23456789
0x0
0x0
0x120
0x0
/usercode/file.cpp: In function 'int main()':
/usercode/file.cpp:38:27: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
38 | printf("0x%xn", htoi("1234"));
| ^~~~~~
/usercode/file.cpp:39:27: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
39 | printf("0x%xn", htoi("0x1234"));
| ^~~~~~~~
/usercode/file.cpp:40:27: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
40 | printf("0x%xn", htoi("0"));
| ^~~
/usercode/file.cpp:41:27: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
41 | printf("0x%xn", htoi("0x0"));
| ^~~~~
/usercode/file.cpp:42:27: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
42 | printf("0x%xn", htoi("0x1234ab"));
| ^~~~~~~~~~
/usercode/file.cpp:43:27: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
43 | printf("0x%xn", htoi("0x1234AF"));
| ^~~~~~~~~~
/usercode/file.cpp:44:27: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
44 | printf("0x%xn", htoi("0x123456789"));
| ^~~~~~~~~~~~~
/usercode/file.cpp:45:27: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
45 | printf("0x%xn", htoi("0x"));
| ^~~~
/usercode/file.cpp:46:27: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
46 | printf("0x%xn", htoi("0s"));
| ^~~~
/usercode/file.cpp:47:27: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
47 | printf("0x%xn", htoi("0x120xab"));
| ^~~~~~~~~~
/usercode/file.cpp:48:27: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
48 | printf("0x%xn", htoi(""));
| ^~
结果显示能输出正确的结果,但是有如下问题:
1. 编译有warning(gcc),warning显示禁止把一个字符串常量转换成char型指针。之所以报这个warning是因为:字符串是一个常量,其保存在程序的只读区,如果把其转换成了char型指针,就会有通过指针修改字符串内容的可能,这可能会导致程序崩溃。为了解决这个问题,需要把函数htoi的入参定义成const类型,这个就不能通过char指针修改字符串了。
2. 和自我解答相比,参考答案中并没有对输入中的异常字符进行报错。也许在一些场景中需要抛出error信息来提醒输入中的错误。
ANSI C 规范定义了 stof()、atoi()、atol()、strtod()、strtol()、strtoul() 共6个可以将字符串转换为数字的函数,包含在stdlib.h库中。
这几个函数的应用参考文章:
C语言atoi()函数:将字符串转换成int(整数)_C语言中文网



