昨天去南匯帶學生的資料結構上機,好累,看到滿眼的c,滿腦的指標,結構體。頭大的不得了!學生的問題也爆怪!遇到兩個問題,雖現在都已經解決,但還是決定放在這裡,供以後使用!(發現c語言真的是博大精深,自己還是欠缺很多!)對了,前天的uclinux也成功裝上去了,不容易啊!
奇怪的死迴圈!!
副以下程式: #include main() {int i; do{ printf("*"); scanf("%d",&i); }while(1); } 這個程式非常的簡單.粗看上去沒有什麼,功能就是每列印一個星號後等待使用者輸入一個整形得值,但問題接種而來,使用者一但輸入的是數字外的各種字元,立刻造成死迴圈.逐步執行也無法跳出.但作為scanf這樣的控制流程函數,無論我的輸入是否正確,他都應在下一次執行時停住等待使用者輸入,但問題是它自動執行了. 為此我做過變數的值跟蹤,發現每次他能自動獲得一個值.且這個值並不是整形量且無序改變.在換了BC編譯以後問題消失.但是當逐步執行後問題依舊出現. |
當輸入字元的時候,把i的內容輸出來。
可以得知 i的值一直保持不變。(且跳過了scanf函數)。
對於scanf()函數可以想象引發一個中斷響應。(引出中斷相應表明一點就是此函數調用了中斷----------等待輸入的中斷)
產生這個響應可能需要一個條件,那就是此函數所開闢或者說是為中斷開闢的緩衝區應是空的!
因此出現這種錯誤的原因可能是緩衝區沒清空。
以‘/n'表示輸入結束(這個說的有不小問題我想,不過為表示一下這麼說的)
然後編譯系統自動在後面加上清空標誌^Z(ctl+z),以為下一次調用。
至於輸入字元就陷入跳過這個語句,可能是因為當初設計這個函數的時候沒有對異常做充分的處理,以至於在讀入第一個字元的時候發現類型不符就停止把他後面的清空標誌^Z傳遞到緩衝區域了。(前面可能說的有點問題,應該說是scan)
在執行scanf時候檢查緩衝區是否為空白,為空白的時候執行,否則不執行(在前一次執行scanf函數的時候沒有把緩衝區清空)。
在進行負值的時候出現類型錯誤,跳轉了語句。沒有執行清空語句。(後面所有的scanf語句都不起作用了,包括子程式中的);
整個main程式結束後才清空;
呵呵~~~~~~
亂想著說的!~最近在看彙編和C++就亂講了一點,呵呵!~C++中也經常把cout的優點和scanf的缺點搞出來講!但具體為什麼會這樣
我想要追究到編譯軟體上面,因為scanf()不是c 的語句而是編譯軟體接受標準定的一個同名的輸入函數 標準就體現在用相同的名字(也就是聲明部分一樣)。但至於scanf()函數的定義體一不一樣,那就不得而知了!~
不過好象不是這個概念。。。是要維持整形輸入不變。。。這樣的改變不是從實質上解決問題而圍繞了個彎逃避問題。。。SCANF是有緩衝的一個輸入語句。不像GETCHAR那樣能直接獲得一個值。。但問題就處在這個輸入緩衝區了。。它裡面值並沒有被處理掉。當然這個是我通過值跟蹤後和我的導師討論出來的結果。。。。。我是想問一下誰能有經驗的話分析一下這個問題的真正錯誤在什麼地方。。如何解決。。我初步覺得應該用彙編。。但是具體的分析和邏輯上還有點亂。。
解決方案:fflush(stdin);在scanf的前面加了一個語句(用來清空鍵盤輸入的緩衝區)