2015-12-08 134 views
0

我試着寫的程序應該能夠讀取長度不超過8個字符的字符串,並檢查這個字符串是否出現在文件中。我決定使用'讀'系統功能,但我已經想出了這個功能的奇怪行爲。由於它是手動編寫的,所以在到達文件末尾時它必須返回0,但在我沒有更多字符的情況下,它仍然讀取'\ n'並返回1(讀取的字節數)(I'已經檢查了讀取字符的ASCII碼,它實際上是'\ n'的10)。所以考慮到這個事實,我改變了我的代碼,它的工作,但我仍然不明白爲什麼這樣的行爲。這裏是我的函數的代碼:'讀'系統函數的奇怪行爲

int is_present(int fd, char *string) 
{ 
    int i; 
    char ch, buf[9]; 

    if (!read(fd, &ch, 1)) //file is empty 
     return 0; 

    while (1) { 
     i = 0; 
     while (ch != '\n') { 
      buf[i++] = ch; 
      read(fd, &ch, 1); 
     } 
     buf[i] = '\0'; 
     if (!strncmp(string, buf, strlen(buf))) { 
      close(fd); 
      return 1; 
     } 
     if(!read(fd, &ch, 1)) //EOF reached 
      break; 
    } 
    close(fd); 
    return 0; 
} 
+0

讀完'\ n'後它終止了嗎? –

+0

'strncmp(string,buf,strlen(buf))'與'strcmp(string,buf)'沒有區別。也許你的意思是'strncmp(string,buf,sizeof(buf))'? –

回答

1

我認爲你的問題是在read()內部調用。你沒有檢查函數的返回。

while (ch != '\n') { 
     buf[i++] = ch; 
     read(fd, &ch, 1); 
    } 

如果進入功能和ch等於'\n'那麼這將是一個無限循環,因爲read()不會修改ch值當文件正好處於EOF。順便說一句,你沒有檢查buf的界限。

+0

我在我的程序的前一個版本中是這樣做的,但正如我所說的,在文件末尾,它讀取了一個額外的'\ n',所以,知道它後,我改變了它。謝謝你的界限 –

+0

@VladislavKolesnikov:那麼你應該發佈你以前的代碼,因爲它是EOF中的'read()'什麼都不做,而且'ch'完全沒有改變。 – rodrigo

+0

哦,我發現我的錯誤。非常感謝你! –

0

我假設的問題是「爲什麼read()工作這種方式」而不是「?什麼是錯我的計劃」

這不是一個錯誤。從manual page

成功時返回讀取的字節數(零表示文件結束),文件位置按此數字提前。如果此數字小於請求的字節數,則不是錯誤;這可能會發生,例如因爲現在實際上可用的字節更少(可能因爲我們接近文件結尾,或者因爲我們正在從管道讀取數據或從終端讀取數據),或者因爲信號中斷了read()。出錯時,返回-1,並適當設置errno。在這種情況下,未指定文件位置(如果有)是否發生更改。

如果你仔細想想read必須這樣工作。如果返回0表示當某個數據已經讀取了,則表示文件已達到文件結尾,但您不知道讀取了多少數據。因此,read僅當由於文件結束條件而未讀取數據時才返回0。

因此,在這種情況下,只有\n可用,read()將成功並返回1.下一次讀取將返回一個零以指示文件結束。

0

read()函數除非發現EOF不斷讀取字符並將其放在緩衝區中。在這種情況下,\n也被認爲是一個字符。因此它也讀取。您的代碼在讀取\n之後就會關閉,因爲除了EOF以外沒有別的。所以只有EOFread()的分隔符,其他所有字符都被認爲是正常的。乾杯!