2012-05-02 21 views
3

我正在檢查Beej的IPC指南,其中一行代碼引起了我的注意。我們可以在沒有&&/||的情況下同時循環測試兩個參數嗎?

在特定頁面中,speak.c中的while循環有兩個條件來檢查while (gets(s), !feof(stdin))

所以我的問題是,這是如何可能的,因爲我已經看到,而大多數時間只看一個條件。

PS:我對這些並不陌生。將不勝感激任何幫助。謝謝!

+1

如果您發現1990年以後使用'gets'寫成的書/指南,您應該刻錄它。作者是無能,你會從閱讀他們的例子撿起非常不良的習慣... ... –

+0

@R .. Beej的指導是af @#國王的暴行,應該從interwebs擦掉,並且引用的代碼應該展示他的在海牙進行首次審判。 – tbert

+0

哇,真的那麼糟...... –

回答

6

該片段

while (gets(s), !feof(stdin)) 

使用逗號操作,第一它執行gets(s),然後它測試!feof(stdin),這是條件的結果。

順便說一句不要用得到,這是非常不安全的。警惕使用它的來源,他們可能不是學習語言的好資源。

代碼

while(gets(s), !feof(stdin)) { 
    /* loop body */ 
} 

相當於

gets(s); 
while(!feof(stdin)) { 
    /* loop body */ 
    gets(s); 
} 

只是更簡潔,因爲它避免了循環前和在循環體的gets的重複。

+0

謝謝!!!這真的讓我明白。 – Shash

2

該測試使用的是comma operator,已被用作使用gets(s)獲取下一行文本並使用!feof(stdin)測試文件結束的方法。

2

此語法不評估兩個表達式。它首先執行gets(s),然後評估!feof(stdin),該函數可能會被gets()函數調用修改。

這不是一個很好的方法,因爲它既使用gets(),這不是一個安全的功能,並且對初學者(因此你的問題)讀起來很不自在。

1

我同意@DanielFischer和@trojanfoe,逗號運算符。

另一點需要注意的是,您通常不想使用它,特別是在上述問題的上下文中。作爲一名專業編碼人員,它會讓你的代碼變得更加可讀,並且讓其他開發人員感到困惑,所以有一次罷工反對它。另外,如果你曾經使用過靜態代碼分析工具,如LINT(http://en.wikipedia.org/wiki/PC-Lint),它會向你吐出大量的警告,所以還有另一個問題是正確的那裏如果你想要專業質量代碼。

最後,正如@DanielFischer指出的那樣,gets()根本就不安全,並且對許多漏洞和溢出漏洞負責。改爲使用fgets()函數,因爲它可以設置要讀取的字符數的上限。

http://www.cplusplus.com/reference/clibrary/cstdio/fgets/

你不會後悔使它成爲一個習慣,在地方總是用fgets()的獲得,尤其是如果這是生產代碼。

您也可以考慮查看安全字符串函數。

http://linux.die.net/man/3/snprintf

它們不是標準ANSI/C99的C部分,但如果你只是對某一個平臺開發,他們阻止你崩潰您的程序或打開安全漏洞。

祝你好運!

+0

謝謝你的建議。會記在心裏。 – Shash

3

一些人已經指出了一些與此有關的問題。我當然同意使用gets(根本)是一個糟糕的主意。

我認爲值得一提的是另一個細節:因爲這使用feof(file)作爲退出循環的條件,所以如果在文件結束之前遇到錯誤,它也可能會行爲不當。發生錯誤時,錯誤標誌將被設置,但(通常)EOF標誌將不會被設置 - 並且由於您不能再從文件讀取(由於錯誤),它永遠不會是這樣,所以這將進入無限循環。

做這項工作的正確途徑是與fgets,並檢查其返回值:

while (fgets(s, length_of_s, stdin)) 
    process(s); 

其測試fgets在從文件中讀取成功,所以它會退出循環的任文件結尾出錯。

另外一個小的細節:當fgets讀取的字符串時,它通常保留在行(其中gets投擲它遠離)的端部的換行。如果不存在換行符,則可能需要添加更多代碼才能將其剝離(如果換行符不存在,可能會處理比分配的緩衝區更長的行)。

+0

+1,用於解釋編寫此代碼的正確方法。 –

+0

+1 from me以及:) – Shash

+0

請注意,如果代碼的原始版本沒有以換行符結束,則原始版本的代碼將丟棄該文件的最後一行。 –

相關問題