簡體   English   中英

在while循環中使用scanf

[英]Using scanf in a while loop

這個非常簡單的問題可能是一個非常簡單的答案:

我正在閱讀Pratta的“C Primer Plus”,他一直在使用這個例子

while (scanf("%d", &num) == 1)...

== 1真的有必要嗎? 似乎可以寫一下:

while (scanf("%d", &num))

似乎相等測試是不必要的,因為scanf返回讀取的對象數,1將使while循環為真。 是確保讀取的元素數量正好為1還是完全多余的原因?

在C中,0被評估為false,其他一切被評估為true。 因此,如果scanf返回EOF,這是一個負值,則循環將評估為true,這不是您想要的。

由於scanf在文件末尾返回值EOF(-1),因此寫入的循環是正確的。 只要輸入包含與%d匹配的文本,它就會運行,並在文件的第一個不匹配或結尾處停止。

如果scanf期待不止一個輸入,那么一眼就會更加清晰......

while (scanf("%d %d", &x, &y)==2) { ... }

當第一次無法匹配兩個值時,將退出循環,這可能是由於文件結束( scanf返回EOF(-1))或輸入匹配錯誤(例如輸入xyzzy 42不匹配) %d %d因此scanf在第一次失敗時停止,並在返回某個小於2的值時返回0 而不寫入xy )。

當然,在解析來自普通人的真實輸入時, scanf 不是你的朋友。 處理錯誤案件有很多陷阱。

編輯:更正了錯誤: scanf在文件末尾返回EOF ,或者計算其成功設置的變量數的非負整數。

關鍵點在於,由於C中的任何非零值都為TRUE ,因此無法在循環中正確測試返回值,這很容易導致意外行為。 特別是, while(scanf(...))是一個無限循環,除非它遇到無法根據其格式轉換的輸入文本。

而且我不能強烈強調scanf 不是你的朋友。 fgetssscanf組合可能足以進行一些簡單的解析,但即使這樣,它也很容易被邊緣情況和錯誤所淹沒。

您正確理解了C代碼。

有時,測試讀取的項目數量的原因是,當輸入與預期類型不匹配時,有人希望確保所有項目都被讀取而不是提前退出scanf。 在這種特殊情況下,沒關系。

通常,scanf是功能較差的選擇,因為它不能滿足人類用戶的交互輸入需求。 通常fgets和sscanf的組合會產生更好的結果。 在這種特殊情況下,沒關系。

如果后面的章節解釋為什么某些編碼實踐比這個簡單的例子更好,那就好了。 但如果沒有,你應該拋棄你正在閱讀的書。

另一方面,您的替代代碼並不完全是替代品。 如果scanf返回-1,則執行while循環。

雖然你是正確的,但並不是絕對必要的,有些人更喜歡它,原因有幾個。

首先,通過比較1,它成為一個顯式的布爾值(true或false)。 如果沒有比較,您將測試一個整數,該整數在C中有效,但在以后的語言中沒有(如C#)。

其次,有些人會根據while([function])來讀取第二個版本,而不是while([返回值]),並且通過測試函數暫時會混淆,當顯然意味着測試返回值時。

這完全取決於個人偏好,就我而言,兩者都是有效的。

有人可能會在沒有明確比較的情況下編寫它(雖然參見JRL的答案),但為什么會這樣呢? 我會說無比較條件只應該用於具有顯式布爾語義的值(例如,像isdigit()調用)。 其他一切都應該使用明確的比較。 在這種情況下( scanf的結果),語義明顯是非布爾值的,因此顯式比較是有序的。

此外,通常可以省略的比較通常是與的比較。 如果你覺得省略與其他東西比較的沖動(比如在這種情況下為1 ),最好三思而后行並確保你知道自己在做什么(再次參見JRL的答案)。

在任何情況下,當可以安全地省略比較並且實際上省略它時,條件的實際語義含義保持不變。 如果您擔心的話,它對結果代碼的效率絕對沒有影響。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM