2013-05-16 49 views
0

我寫了一下C99代碼從標準輸入讀取:發現錯誤,標準錯誤

// [...] 
fgets(buf, sizeof(buf), stdin); 
// [...] 

但我知道如果我要趕在此情況下的錯誤,因爲外殼可以重定向stdin任何東西這可能不如普通的stdin。但這也意味着,必須檢查stdin,stdoutstderr上的每個訪問是否有錯誤,並且我很少看到printf和CO之後的任何檢查。

那麼,是否建議檢查每個流訪問錯誤?然後

上面的例子會是這樣的:

// [...] 
if (!fgets(buf, sizeof(buf), stdin) && ferror(stdin)) { 
    exit(EXIT_FAILURE); 
} 
// [...] 

提前感謝!

回答

1

這取決於您正在開發的應用程序的性質。例如,如果您正在開發一個硬實時系統,其異常終止導致嚴重問題。那麼你應該採取預防措施來處理各種數據流錯誤。在這種情況下,請使用以下代碼:

if (!fgets(buf, sizeof(buf), stdin) && ferror(stdin)) { 
    exit(EXIT_FAILURE); 
} 

或某些與其類似的構造。但是,如果您的應用程序的罕見故障不會有任何嚴重後果,您不需要檢查每個數據流操作。

3

您每次使用時都必須檢查返回值fgets()。如果你不這樣做,你不知道緩衝區中是否有有用的數據;它可以再次保持最後一行。類似的評論適用於每個讀取操作;您必須檢查讀取操作是否返回了您的預期。

if (fgets(buf, sizeof(buf), stdin) == 0) 
    ...EOF, or some error... 

在處理代碼中,您需要決定要做什麼。您可以在該代碼中合法使用feof()ferror()。對問題的正確反應取決於您的代碼。檢測EOF通常是退出循環或退出函數的原因(breakreturn,但只有在函數未打開文件時才返回;否則必須至少關閉文件)。在stdin上檢測錯誤將是一件罕見的事情;你將不得不決定什麼是適當的。

在寫入stderrstdout時檢測錯誤是不經常做的事情,但它可以說是草率編程以省略它們。有一個問題,特別是如果是stderr有問題,則是「你將如何報告錯誤?」您可能需要使用syslog(),但這是您必須考慮的問題。

+0

謝謝,我從來沒有聽說過syslog。很高興知道。但關於EOF:有時,我有一個預先初始化的緩衝區,不在乎它是否沒有改變,但是你是對的,我應該始終關心返回值。 – user1678062

0

這是一個有趣的練習。找到某人的交互式程序,運行它直到它詢問來自終端的輸入,然後按下control-D(EOF)。可能的原因是作者沒有檢查feof(stdin),他的gets()調用只是返回代碼解釋爲空行的0個字節。如果將它視爲無效輸入並重新提示,它將以無限循環結束!