[英]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.