我正在檢查Beej的IPC指南,其中一行代碼引起了我的注意。我們可以在沒有&&/||的情況下同時循環測試兩個參數嗎?
在特定頁面中,speak.c
中的while循環有兩個條件來檢查while (gets(s), !feof(stdin))
。
所以我的問題是,這是如何可能的,因爲我已經看到,而大多數時間只看一個條件。
PS:我對這些並不陌生。將不勝感激任何幫助。謝謝!
我正在檢查Beej的IPC指南,其中一行代碼引起了我的注意。我們可以在沒有&&/||的情況下同時循環測試兩個參數嗎?
在特定頁面中,speak.c
中的while循環有兩個條件來檢查while (gets(s), !feof(stdin))
。
所以我的問題是,這是如何可能的,因爲我已經看到,而大多數時間只看一個條件。
PS:我對這些並不陌生。將不勝感激任何幫助。謝謝!
該片段
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
的重複。
謝謝!!!這真的讓我明白。 – Shash
該測試使用的是comma operator,已被用作使用gets(s)
獲取下一行文本並使用!feof(stdin)
測試文件結束的方法。
此語法不評估兩個表達式。它首先執行gets(s)
,然後評估!feof(stdin)
,該函數可能會被gets()
函數調用修改。
這不是一個很好的方法,因爲它既使用gets()
,這不是一個安全的功能,並且對初學者(因此你的問題)讀起來很不自在。
我同意@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部分,但如果你只是對某一個平臺開發,他們阻止你崩潰您的程序或打開安全漏洞。
祝你好運!
謝謝你的建議。會記在心裏。 – Shash
一些人已經指出了一些與此有關的問題。我當然同意使用gets
(根本)是一個糟糕的主意。
我認爲值得一提的是另一個細節:因爲這使用feof(file)
作爲退出循環的條件,所以如果在文件結束之前遇到錯誤,它也可能會行爲不當。發生錯誤時,錯誤標誌將被設置,但(通常)EOF標誌將不會被設置 - 並且由於您不能再從文件讀取(由於錯誤),它永遠不會是這樣,所以這將進入無限循環。
做這項工作的正確途徑是與fgets
,並檢查其返回值:
while (fgets(s, length_of_s, stdin))
process(s);
其測試fgets
在從文件中讀取成功,所以它會退出循環的任文件結尾或出錯。
另外一個小的細節:當fgets
讀取的字符串時,它通常保留在行(其中gets
投擲它遠離)的端部的換行。如果不存在換行符,則可能需要添加更多代碼才能將其剝離(如果換行符不存在,可能會處理比分配的緩衝區更長的行)。
如果您發現1990年以後使用'gets'寫成的書/指南,您應該刻錄它。作者是無能,你會從閱讀他們的例子撿起非常不良的習慣... ... –
@R .. Beej的指導是af @#國王的暴行,應該從interwebs擦掉,並且引用的代碼應該展示他的在海牙進行首次審判。 – tbert
哇,真的那麼糟...... –