如果我想将单个数字char
转换为数字值,例如,如果:
char c = '5';
并且我希望c
保留5
而不是'5'
,它是100%可移植的吗?
c = c - '0';
我听说所有字符集都按连续顺序存储数字,所以我假设这样,但我想知道是否有一个有组织的库函数来进行这种转换,以及它是如何按常规方式完成的。我是一个真正的初学者:)
答案 0 :(得分:27)
是的,这是一种安全的转换。 C要求它起作用。此保证在最新的ISO C标准的第5.2.1节第2节中,最近的草案是N1570:
基本源和基本执行字符集应具有以下内容 成员:
[...]
10位小数位数
0 1 2 3 4 5 6 7 8 9
[...]
在源和执行基本字符集中, 上述小数位数列表中0后的每个字符的值应大于1 以前的价值。
ASCII和EBCDIC以及从它们派生的字符集都满足这一要求,这就是C标准能够强加它的原因。请注意,字母不连续iN EBCDIC,而C不要求它们。
单个char
没有库函数,你需要先构建一个字符串:
int digit_to_int(char d)
{
char str[2];
str[0] = d;
str[1] = '\0';
return (int) strtol(str, NULL, 10);
}
一旦有字符串,您也可以使用atoi()
函数进行转换,但strtol()
更好更安全。
正如评论者指出的那样,调用函数进行这种转换是极端的过度杀伤力;你最初减去'0'的方法是这样做的正确方法。我只想说明如何使用推荐的标准方法将数字转换为字符串转换为“真实”数字。
答案 1 :(得分:9)
试试这个:
char c = '5' - '0';
答案 2 :(得分:5)
您可以使用atoi
,它是标准库的一部分。
答案 3 :(得分:5)
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 */
}
这会将单个十六进制字符(大写或小写独立)转换为整数。
答案 4 :(得分:2)
由于您只转换一个字符,因此atoi()函数过度。如果要转换数字的字符串表示,atoi()非常有用。其他帖子举例说明了这一点。如果我正确阅读了您的帖子,您只会转换一个数字字符。因此,您只需要转换0到9范围内的字符。在仅转换一个数字字符的情况下,您建议减去“0”将为您提供所需的结果。这有效的原因是因为ASCII值是连续的(就像你说的那样)。因此,从数字字符中减去ASCII值0(ASCII值48 - 参见值ASCII Table)将给出数字的值。所以,你的例子是c = c - '0',其中c ='5',实际发生的是53(ASCII值为5) - 48(ASCII值为0)= 5.
当我第一次发布这个答案时,我没有考虑你关于在不同字符集之间100%移植的评论。我做了一些进一步环顾四周,似乎你的答案仍然大多是正确的。问题是您使用的是8位数据类型的char。哪个不适用于所有字符类型。请阅读Joel Spolsky on Unicode的这篇文章,了解有关Unicode的更多信息。在这篇文章中,他说他使用wchar_t作为字符。这对他来说效果很好,他以29种语言出版了他的网站。因此,您需要将char更改为wchar_t。除此之外,他说127以下的角色基本相同。这将包括代表数字的字符。这意味着你提出的基本数学应该适用于你想要实现的目标。
答案 5 :(得分:1)
是。只要您使用标准的ascii字符,这就是安全的,就像您在此示例中一样。
答案 6 :(得分:0)
通常情况下,如果无法保证您的输入位于“0”..“9”范围内,则必须执行以下检查:
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
}
P.S。我知道这是 overkill 。我只是想把它作为一种可能不会立即明显的替代解决方案。
答案 7 :(得分:0)
正如其他人所建议的,但包含在一个功能中:
int char_to_digit(char c) {
return c - '0';
}
现在只需使用该功能。如果,在线下,您决定使用不同的方法,您只需要更改实现(性能,字符集差异,无论如何),您将不需要更改调用者。
此版本假定c包含表示数字的char。您可以在调用函数之前使用ctype.h的isdigit函数检查它。
答案 8 :(得分:0)
由于'0','1','2'....的ASCII码从48到57放置,因此它们基本上是连续的。现在算术运算需要将char数据类型转换为int数据类型。你基本上做的是: 53-48因此它存储了值5,您可以使用它来执行任何整数运算。注意,在从int转换回char时,编译器不会给出错误,只是执行模256操作以将值放在可接受的范围内
答案 9 :(得分:0)
您只需使用atol()
功能:
#include <stdio.h>
#include <stdlib.h>
int main()
{
const char *c = "5";
int d = atol(c);
printf("%d\n", d);
}