如果我想将单个数字char
转换为其数值,例如:
char c = '5';
我想让c
保存5
而不是'5'
,这样做是否百分之百可移植?
c = c - '0';
我听说所有字符集都按顺序存储数字,所以我认为可以这样做,但我想知道是否有组织的库函数来进行此转换,以及常规的处理方式是什么。我是一个真正的初学者 :)
ASCII和EBCDIC以及从它们派生的字符集都满足此要求,这就是为什么C标准能够强制实施它的原因。请注意,字母在EBCDIC中不是连续的,并且C语言不要求它们连续。基本源字符集和基本执行字符集都必须包含以下成员:
[...]
十个十进制数字
0 1 2 3 4 5 6 7 8 9
[...]
在源字符集和执行字符集中,上述十进制数字列表中每个数字之后的每个字符的值都应比前一个大1。
char
的库函数,您需要先构建一个字符串:int digit_to_int(char d)
{
char str[2];
str[0] = d;
str[1] = '\0';
return (int) strtol(str, NULL, 10);
}
atoi()
函数在获得字符串后进行转换,但是strtol()
更好、更安全。char c = '5' - '0';
int i = c - '0';
请注意,此方法不会对字符进行任何验证 - 例如,如果字符是 'a',那么您将得到 91-48 = 49。特别是当您处理用户或网络输入时,应该执行验证以避免程序中的错误行为。只需检查范围:
if ('0' <= c && c <= '9') {
i = c - '0';
} else {
/* handle error */
}
if ('0' <= c && c <= '9') {
i = c - '0';
} else if ('a' <= c && c <= 'f') {
i = 10 + c - 'a';
} else if ('A' <= c && c <= 'F') {
i = 10 + c - 'A';
} else {
/* handle error */
}
这将把一个单独的十六进制字符(大小写无关)转换为整数。
是的。只要您使用标准 ASCII 字符,就像在此示例中一样,这是安全的。
atol()
函数:#include <stdio.h>
#include <stdlib.h>
int main()
{
const char *c = "5";
int d = atol(c);
printf("%d\n", d);
}
if (c >= '0' && c <= '9') {
int v = c - '0';
// safely use v
}
另一种选择是使用查找表。您可以通过更少的代码(可能更快)进行简单的范围检查和转换:
// one-time setup of an array of 256 integers;
// all slots set to -1 except for ones corresponding
// to the numeric characters
static const int CHAR_TO_NUMBER[] = {
-1, -1, -1, ...,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, // '0'..'9'
-1, -1, -1, ...
};
// Now, all you need is:
int v = CHAR_TO_NUMBER[c];
if (v != -1) {
// safely use v
}
顺便说一下,我知道这有点过头了。我只是想把它作为一个可能不会立即显而易见的替代方案呈现出来。
正如其他人所建议的那样,但包装在一个函数中:
int char_to_digit(char c) {
return c - '0';
}
现在只需使用该函数。如果在以后的某个时候,您决定使用不同的方法,您只需要更改实现(性能、字符集差异等),而不需要更改调用者。
此版本假设c包含表示数字的char。您可以在调用函数之前使用ctype.h的isdigit函数进行检查。
由于'0','1','2'....的ASCII代码从48到57排列,它们本质上是连续的。现在,算术运算需要将char数据类型转换为int数据类型。因此,你基本上正在做的是:53-48,因此它存储值5,你可以使用任何整数操作。请注意,在从int转换回char时,编译器不会给出错误,而只是执行模256操作以将值放入其可接受的范围内。