[英]Converting string to a number
我遇到了这个C程序:
int main() {
printf("Enter your address, (e.g. 51 Anzac Road) ");
gets(address);
number = 0;
i = 0;
while (address[i] != ' ') {
number = number * 10 + (address[i] - 48);
i++;
}
}
我知道number = number * 10 + (address[i] - 48);
是从输入中获取数字,但是有人可以向我解释这是如何工作的吗? 如何从输入中产生数字?
在ASCII中,数字字符 '0'
至'9'
占据代码点48至57(i hex, 0x30
至0x39
),因此,要将数字字符转换为值,只需减去48。
顺便说一句,您确实应该减去
'0'
因为该标准不保证ASCII,尽管它确实保证了数字字符是连续且有序的。 例如,z / OS下的C使用EBCDIC,它将数字放置在代码点0xf0
至0xf9
。
循环本身是一种简单的移位加法类型,可以从多个数字字符中创建一个数字。 假设您有字符串"123"
,且number
最初为零。
将number
(零)乘以10得到零,然后加上数字字符'1'
(49)并减去48。这得到一个。
然后,将number
(一)乘以十得到十,并加上数字字符'2'
(50),再减去48。这便得出十二。
最后,将number
(十二)乘以十得到一百二十,然后加上数字字符'3'
(51)并减去48。这将得出一百二十三。
在C标准库, atoi
或更强大的strtol
型函数中,有更好的方法可以在stdlib.h
找到它们。 后者使您可以更好地检测数字末尾是否有“垃圾”,以帮助进行验证( atoi
无法分辨123
和123xyzzy
之间的区别)。
而且,除其他外,您应该避免像瘟疫一样使用gets()
。 就像“ naked” scanf("%s")
,它不适合用户输入,并打开您的代码以缓冲溢出问题。 实际上,与scanf()
不同, 没有安全的方法可以使用gets()
,这无疑就是为什么将其从最新标准C11中删除的原因。 可以在此处找到更强大的用户输入功能。
还有一大类地址,该代码将严重地失败,例如:
3/28 Tivoli Rd
57a Smith Street
Flat 2, 12 Xyzzy Lane
C要求将数字0
到9
以此顺序连续存储在执行字符集中。 48
是ASCII值'0'
,因此,例如:
'3' - 48 == 3
对于任何数字。
C不需要ASCII,因此更好的是:
'3' - '0'
因为虽然48
对ASCII是正确的,但从定义上来说, '0'
对任何字符集都是正确的。
如果address
包含"456 "
,则:
i == 0
且number == 0
, number * 10 + (address[0] - 48)
等于0 * 10 + 4
或4
。 i == 1
, number * 10 + (address[1] - 48)
为4 * 10 + 5
或45
。 i == 2
, number * 10 + (address[2] - 48)
为45 * 10 + 6
或456
到此为止。
永远不要使用gets()
,这很危险,甚至不再是C的一部分。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.