将字符串转换为数字

时间:2014-10-07 01:55:12

标签: c

我遇到了这个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);是从输入中获取数字,但有人可以向我解释这是如何工作的吗?这是如何从输入中产生数字的?

2 个答案:

答案 0 :(得分:4)

在ASCII中,数字字符 '0''9'占用代码点48到57(我是十六进制,0x300x39)所以,要将数字字符转换为值,您只需减去48。


  

顺便说一下,你应该真的减去'0',因为标准不保证ASCII,尽管它确保保证数字字符是连续和有序的。例如,z / OS下的C使用EBCDIC,它将数字放在代码点0xf00xf9


循环本身是一种简单的移位和添加类型,用于从多个数字字符创建数字。假设你有字符串"123",而number最初为零。

你将number(零)乘以10得到零,然后加上数字字符'1'(49)并减去48.这给你一个。

然后你将number(一)乘以10得到十并加上数字'2'(50),再减去48.这给你十二。

最后,你将number(十二)乘以10得到一百二十,然后加上数字字符'3'(51)并减去48.这给你一百二十三。

有更好的方法可以在C标准库atoi或更强大的strtol - 类型函数中执行此操作,所有这些都可以在stdlib.h中找到。后者可以让你更好地检测是否有垃圾"在数字的末尾,有关验证的帮助(atoi无法区分123123xyzzy)。


而且,除了另一个之外,你应该像瘟疫一样避免gets()。它就像"裸体" scanf("%s"),不适合用户输入,并打开代码来缓冲溢出问题。实际上,与scanf()不同,没有使用gets()的安全方式,这无疑是它从最新标准C11中删除的原因。可以找到更健壮的用户输入函数here

还有一大类地址,其代码将失败,例如:

3/28 Tivoli Rd
57a Smith Street
Flat 2, 12 Xyzzy Lane

答案 1 :(得分:4)

C要求数字09按顺序连续存储在执行字符集中。 48'0'的ASCII值,例如:

'3' - 48 == 3

任何数字。

C不需要ASCII,因此更好:

'3' - '0' 

因为虽然48适用于ASCII,但根据定义,'0'适用于任何字符集。

如果address包含"456 ",则:

  • i == 0number == 0number * 10 + (address[0] - 48)等于0 * 10 + 44
  • i == 1number * 10 + (address[1] - 48)4 * 10 + 545
  • i == 2number * 10 + (address[2] - 48)45 * 10 + 6456

你已经完成了。

永远不要使用gets(),这很危险,甚至不再是C的一部分。