2016-07-17 21 views
0

此代碼片段來自CodeChef中Problem問題的成功提交,爲了使其更快速,編碼器使用getchar_unlocked來讀取整數。但我沒有得到它如何在下面的代碼片段中退出循環?請任何人都可以幫助我?完整的代碼可以找到here如何使用getchar_unlocked(),我沒有得到以下代碼中的流?

#include <stdio.h> 
#define g getchar_unlocked 

int read() 
{ 
     int n=0; 
     char c=g(); 

     while(c<'0' || c>'9') 
     { 
       c=g(); 
     } 
     while(c>='0' && c<='9') 
     { 
       n = (n<<3) +(n<<1) +c - '0'; 
       c=g(); // putting it here is giving a unusual behaviour!!!!! like not taking the input and coming out of loop ??? 
     } 
     return n; 
} 
+0

所以'g()'的定義在哪裏? – YakovL

+0

對不起,我沒有粘貼完整的鱈魚,但是如果你打開這個鏈接https://www.codechef。com/viewsolution/10306107,你會得到完整的代碼 – saiflash

+0

什麼是不尋常的行爲? – immibis

回答

1

不錯,定義一個名爲read全局函數(或在列表中http://pubs.opengroup.org/onlinepubs/9699919799/idx/functions.html任何其他名稱)可能導致C庫發生故障,但我不確定這是否會在C標準所使用的意義上達到「未定義行爲」的水平,並且我實際上無法在任何可以方便訪問的操作系統上發生問題。

所以,忽略了,這就是你關於又問循環:

while (c >= '0' && c <= '9') 
    { 
      n = (n<<3) + (n<<1) + c - '0'; 
      c = getchar_unlocked(); 
    } 

你說什麼你不明白的是「如何走出循環」。首先,getchar_unlocked就像getchar,除了它不是線程安全的(因此可能會更快)。它從標準輸入順序返回字符。只要返回的字符大於或等於'0'且小於或等於'9'while循環週期; C標準保證數字是該範圍中唯一的字符,並且它們以正確的順序出現。因此,如果程序的輸入是「1234」,則循環應該循環四次然後停止,因爲在4之後返回的值將是'\n'EOF,它們都不是'0'..'9 '範圍...

char c = getchar_unlocked(); 

...除了程序員在用stdio編程時犯了一個最基本的錯誤。 EOF是一個值超出char可表示的範圍之外,因此要正確存儲該值,應該將c聲明爲int。該錯誤被ASCII(和EBCDIC)的佈局所掩蓋,但在一個假設的實現中,其中char已簽名,EOF的值爲-1,並且所有這些都是允許的 - 程序將進入無限在EOF循環。

0

read是用於在C庫中實現低級輸入的庫函數。不要在你的代碼中使用這個名字作爲函數,你正在創建一個導致未定義行爲的衝突。重命名你的功能。

在我的系統(OS/X)上,你的程序運行正常,你的函數讀取並忽略非數字,解析一個十進制數並返回它。如果您的系統出現問題,可能與重新定義read有關,該問題很容易解決。

請注意,您應該的getchar_unlocked()返回值存儲到int和比較,EOF如果沒有編號的文件年底前發現,以避免不斷地循環。

這裏是一個改進版本:

#include <stdio.h> 

#define g getchar_unlocked 

int read_number(void) { 
    int n = 0; 
    int c = g(); 

    while (c < '0' || c > '9') { 
     if (c == EOF) 
      return -1; 
     c = g(); 
    } 
    while (c >= '0' && c <= '9') { 
     n = (n << 3) + (n << 1) + c - '0'; 
     c = g(); 
    } 
    // you might want to ungetc(c, stdin); to keep the first non digit 
    // character in the standard input buffer for further parsing. 
    return n; 
} 

int main(void) { 
    int val = read_number(); 
    printf("value: %d\n", val); 
    return 0; 
} 
+0

感謝,chqrlie這個信息。下次我會記住這一點。 – saiflash

+0

但是,我在我的問題描述中給出了一個鏈接,可以幫助我理解鏈接中代碼的流程。 – saiflash

+0

Yeap,如果這可能是行爲的原因,你應該指定,否則這聽起來「不是答案」(雖然完全值得它的評論點) – YakovL

相關問題