初學UNIX C時的一點小收穫 (轉)
下面是我以前寫程式碼時遇到的一個小,問題不大,但是忙活了好半天!下面我就用比較正是的方式來將這段經歷送給大家。
請在vi編輯器下編寫這段程式碼.
/*a.c*/
#include
main()
{
int I = 0;
while(I != 1)
{
scanf(“%d”, &I);
}
}
我曾經問過幾個朋友:這段程式碼有沒有問題;都說:應該沒問題吧!那麼我們來測試一下。
我們先寫一段簡單的makefile
下面在下輸入
$vi makefile
在vi編輯器下編輯下面這段程式碼
#這是一段makefile程式碼
#作用是:編譯a.c成可a
HEADERS = include/stdio.h
S = a.c
PRODUCT = a
CC = cc
$(PRODUCT):$(SOURCE)
$(CC) -o $(PRODUCT) $(SOURCES)
編輯完成後,我們來執行makefile
$ make
cc -o a a.c
現在一個可執行的a已經生成了,下面開始寫我們的單元測試計劃
測試編 號
輸入
輸出
測試結果
分析
1
1
跳出
:namespace prefix = o ns = "urn:schemas--com::office" />
2
2
進入下一次輸入狀態
3
1.2
跳出
4
1.9
跳出
5
0.9
進入下一次輸入狀態
6
a
進入下一次輸入狀態
$ a
1
$
…
…
…
邊測試邊填寫測試計劃表
測試編 號
輸入
輸出
測試結果
分析
1
1
跳出
正確
2
2
進入下一次輸入狀態
正確
3
1.2
跳出
正確
4
1.9
跳出
正確
5
0.9
進入下一次輸入狀態
正確
6
a
進入下一次輸入狀態
看樣子沒問題,還有一步就完成了,輸入一個非數值,a,回車!好像沒問題!再輸入1回車!!問題出現了!沒有退出迴圈!Ctrl+c退出吧!
$ a.out
a
1
^C$
測試編 號
輸入
輸出
測試結果
分析
1
1
跳出
正確
此程式碼有一處嚴重錯誤將不予以釋出
2
2
進入下一次輸入狀態
正確
3
1.2
跳出
正確
4
1.9
跳出
正確
5
0.9
進入下一次輸入狀態
正確
6
a
進入下一次輸入狀態
出錯
為什麼會這樣呢?出現了嚴重的,馬上。首先讓我們在scanf語句後面加上一句:
printf(“%d”, I),看一看究竟I後來發生了什麼樣的變化,然後重複編號6的測試步驟,你會發現程式執行進入了死迴圈!它在不停的列印0!也就是說scanf根本不執行了!為什麼會這樣呢?我們的scanf 去哪裡了?經過一番認真學習和聽取老師們的指導終於明白,原來是這樣的。先看下面的概念。
scanf在發生輸入錯或者讀到了EOF,scanf立即返回,如果它讀入了一個不正確字元(如,在應是數字的地方出現了字母),它也立即返回。scanf返回它所完成的轉換的數目;如果它沒有完成任何轉換,則它返回EOF。
scanf在讀到一個換行符時才停止。除非清除換行符,否則它將保留在標準輸入裝置的緩衝區中。如果程式設計師在第二次scanf前沒有清除輸入緩衝區,則會產生錯誤的結果。
下面我們做個實驗,將程式碼改寫成以下。
#include
main()
{
int i = 0;
int j = 0;
char buffer[256];
while( i != 1 )
{
fgets( buffer, 256, stdin );
printf( "****** %s ******** ", buffer );
fflush( stdin );
j = scanf( "%d", &i );
printf( "%d ", j );
}
編譯並執行,先輸入任意一個值,比如a;這時候列印出來的輸入緩衝區結果是a;然後再輸入一個數字,比如2,這時候scanf將返回一個1,以示輸入轉換成功,同時輸入緩衝區將會被清理,所以沒有任何值輸出。
接下來我們再試著輸入一個a,回車,這時候scanf將返回一個0,以示輸入轉換出錯,另外緩衝區中將會列印出a及回車,由此可見在接下來如果沒有對緩衝區進行fflush的話,scanf將會接受到這個在輸入緩衝區的a和回車,從而進入死迴圈!
也就是說剛才我們進行的輸入,在輸入了字母然後回車,scanf返回了一個EOF,而這個結果將會保留在緩衝區中,當下一次程式呼叫scanf時,由於這個輸入緩衝區中所記憶的錯誤,scanf將不會正確執行,從而致使I的值無法改變,從而程式成了一個死迴圈!
問題找到了,解決的方法就是在呼叫scanf之前清除緩衝區,即在其前面加上:
fflush( stdin );
/*a.c*/
#include
main()
{
int I = 0;
while(I != 1)
{
fflush( stdin );
scanf(“%d”, &I);
}
}
這下再一次測試這段程式碼!再接下來該幹什麼幹什麼吧!
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-963478/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 有點收穫了。
- C++中UNIX時間戳與日期互轉C++時間戳
- 記一次三個小時面試的收穫,這些問題你能回答嗎?面試
- 使用Vue3.0,我收穫了哪些知識點(一)Vue
- [譯] React Native 中那些令我收穫頗豐的痛點React Native
- C語言初學者(自學)做的一個猜數字小遊戲C語言遊戲
- 張一鳴:我的大學四年收穫及工作感悟
- C++24小時制轉換成12小時制C++
- 工作間隙整理學習內容的意外收穫
- unix時間轉換為datetimedatetime轉換為unixtime
- 每次的挫敗,都是收穫
- 如何將UTC時間轉換為Unix時間戳(How to convert UTC time to unix timestamp)時間戳
- 「有點收穫」三種基本方法建立執行緒執行緒
- 關於2021年的一些收穫和思考
- 當初自學C++時的筆記記錄C++筆記
- 堅持就有收穫,厲害,贊一個
- 2019 年的收穫與成長
- 【老男孩教育學員故事】0基礎轉行學網安,成功收穫年薪20w+!
- 老男孩教育 | 98年0基礎轉行,三個月時間,收穫滿意Offer!
- Event Loop事件迴圈,看完你總會有點收穫!OOP事件
- 本文幫你在 Unix 下玩轉 C 語言
- 老男孩教育 | 低收入低學歷0基礎轉行,成功收穫21kOffer!
- 老男孩教育 | 28歲轉行學Linux,努力5個月,收穫年薪20w!Linux
- 初學C++的一些小細節(1)C++
- C#初學C#
- 《人工智慧教育技術學》收穫記錄1人工智慧
- (C++伺服器學習筆記):報文多次收發轉為一次收發C++伺服器筆記
- 如何讓網站收穫好的排名?網站
- 從一次線下讀書會獲得的收穫
- 做小遊戲要趟那些坑?手遊團隊轉型一年來的收穫與思考遊戲
- 2020年初在這些股票上投資100美元你會收穫多少?
- 1小時學會Git玩轉GitHubGithub
- 【GoLang 那點事】Go 指標,如此輕鬆掌握,希望有收穫Golang指標
- 初學Java時沒有理解的一些概念Java
- 初學 GoLang 遇到的一個關於時間的坑...Golang
- 初學者轉行學Python合適還是C語言合適?PythonC語言
- 談談WhatsApp一年設計經歷和收穫APP
- 百度飛槳PaddlePaddle影像分割7日學習收穫
- 提供一個論文的組織(命名)方式,記錄自己的理解收穫