2012-12-04 43 views
-1

我遇到了一個編程問題,我只知道答案的一部分。C++中的一元操作

int f(char *p) 
{ 
int n = 0 ; 
while (*p != 0) 
n = 10*n + *p++ - '0' ; 
return n ; 
} 

這是我認爲程序正在做的事情。 p是一個指針,while循環是DE摺疊指針的值直到它等於0.但是我不明白n賦值行,'0'在做什麼?我假設p的值最初是負值,這是增量後它將達到0的唯一方式。

+2

我認爲''0'應該是'0',以便它將'1'變成'1'等。 – chris

回答

3

你混淆零(沒有,沒有)與字符0(圓圈,可能中間有一條斜線)。注意零點在刻度標記中,所以它是字符「0」,而不是數字零。

'0' - '0'= 0
'1' - '0'= 1
'2' - '0'= 2
...

因此,通過減去字符從數字零開始,您會得到與該數字對應的數字。因此,假設你有這個數字序列:'4','2','1'。你如何從這個數字中得到412位數字?你把'4'變成四。然後你乘以十。現在你有四十歲了。將'2'轉換爲兩個並添加它。現在你有四十二個。乘以十。把'1'轉換成一個,然後加上,現在你有四百二十一個。

這就是你如何將數字序列轉換爲數字。

+0

那麼,什麼樣的價值觀才能成立呢?當我們反思他們時,我們會得到什麼? – Josh

+0

'p'包含一個數字序列,如「421」。當我們去引用它們時,我們會得到'0','1'等字符。該函數將由數字序列組成的字符串轉換爲數字序列在數字10中表示的數字。 –

2

n局部變量累加傳遞給該函數的十進制數的值在字符串中。這是atoi的實現,沒有有效性檢查。

這裏是循環體的運作:

n = 10*n + *p++ - ‘0'; 

分配到n在指針p由10個加上當前字符碼的n的先前值相乘的結果較少的零碼;在取消引用後增量p

由於數字字符是按順序編碼的,因此*p-'0'表達式表示一個數字的十進制值。

假設您正在解析字符串"987"。當你通過循環時,n從零開始;然後它被分配以下值:

n = 10*0 + 9; // That's 9 
n = 10*9 + 8; // That's 98 
n = 10*98 + 7; // That's 987 
+0

你能解釋一下「n = ...」這條線是如何工作的嗎? – Josh

1

至少可以這樣寫得不好。

0)所使用的格式化!:

int f(char* p) 
{ 
    int n = 0; 

    while (*p != 0) 
     n = 10*n + *p++ - ‘0?; 

    return n; 
} 

1)?有語法上無效。它可能應該是一個'由克里斯指出(和您現有的是錯的太多,但是這可能是因爲你從一個網站,而不是一個源文件複製它),贈送:

int f(char* p) 
{ 
    int n = 0; 

    while (*p != 0) 
     n = 10 * n + *p++ - '0'; 

    return n; 
} 

2)參數類型並不像它應該那樣有約束力。由於*p絕不會被修改(根據我們的目標),我們應該強制執行,以確保我們沒有犯任何錯誤:

int f(const char* p) 
{ 
    int n = 0; 

    while (*p != 0) 
     n = 10 * n + *p++ - '0'; 

    return n; 
} 

3)原來的程序員明顯過敏可讀的代碼。讓我們分手了我們的業務:

int f(const char* p) 
{ 
    int n = 0; 

    for (; *p != 0; ++p) 
    { 
     const int digit = *p - '0'; 
     n = 10 * n + digit; 
    } 

    return n; 
} 

4)現在的操作更加明顯一點,我們可以看到一些獨立嵌入該功能功能;這應該被分解出來(這被稱爲反應堆)成一個單獨的功能。

也就是說,我們看到的converting a character to a digit操作:)

int todigit(const char c) 
{ 
    // this works because the literals '0', '1', '2', etc. are 
    // all guaranteed to be in order. Ergo '0' - '0' will be 0, 
    // '1' - '0' will be 1, '2' - '0' will be 2, and so on. 

    return c - '0'; 
} 

int f(const char* p) 
{ 
    int n = 0; 

    for (; *p != 0; ++p) 
     n = 10 * n + todigit(*p); 

    return n; 
} 

5所以,現在很明顯的功能通過讀取字符的字符串的字符和數字產生了一些數字。已經exists under the name atoi, and this function is an unsafe implementation此功能:

int todigit(const char c) 
{ 
    // this works because the literals '0', '1', '2', etc. are 
    // all guaranteed to be in order. Ergo '0' - '0' will be 0, 
    // '1' - '0' will be 1, '2' - '0' will be 2, and so on. 

    return c - '0'; 
} 

int atoi_unsafe(const char* p) 
{ 
    int n = 0; 

    for (; *p != 0; ++p) 
     n = 10 * n + todigit(*p); 

    return n; 
} 

它作爲一個練習的讀取來檢查溢出,無效字符(那些沒有數字),等等。但是,這應該讓事情變得更加清晰,首先應該如何寫出這樣的功能。

1

這是一個字符串到數字的轉換函數。類似於atoi

字符串是一系列字符。因此,內存中的「123」將爲: '1','2','3',NULL

p指向它。

現在,根據ASCII,digits are encoded from '0' to '9'。 '0'被賦值爲48,'9'被賦值爲57.因此,'1','2','3',NULL在內存中實際上是:49,50,51,0

如果您想從字符'0'轉換爲整數0,則必須從內存中的值中減去48。你看到這是怎麼回事?

現在,不是減去數字48,而是減去'0',這使代碼更易於閱讀。