初學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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 在alter database mount時的一點收穫Database
- 閱讀C語言教材的一些收穫C語言
- 巴菲特Twitter帳號3小時收穫14萬粉絲
- 記一次三個小時面試的收穫,這些問題你能回答嗎?面試
- 使用Vue3.0,我收穫了哪些知識點(一)Vue
- Linux:成熟收穫或泡沫破裂(轉)Linux
- [轉] 一個小時學會GitGit
- 初學Oracle的一點心得Oracle
- 一小時學會 C# 6.0C#
- MBA國際貿易課程學習中的一些收穫
- 工作間隙整理學習內容的意外收穫
- 昨晚的收穫DB2DB2
- [譯] React Native 中那些令我收穫頗豐的痛點React Native
- MBA國際貿易課程學習中的一些收穫(二)
- 「有點收穫」三種基本方法建立執行緒執行緒
- 一小時學會 C# 6 的新特性C#
- C++中UNIX時間戳與日期互轉C++時間戳
- 開發者總結AAA遊戲開發經歷的5點收穫遊戲開發
- Event Loop事件迴圈,看完你總會有點收穫!OOP事件
- 給初學java的一點建議Java
- 《人工智慧教育技術學》收穫記錄1人工智慧
- 如何讓網站收穫好的排名?網站
- 【老男孩教育學員故事】0基礎轉行學網安,成功收穫年薪20w+!
- C++24小時制轉換成12小時制C++
- 關於2021年的一些收穫和思考
- 老男孩教育 | 98年0基礎轉行,三個月時間,收穫滿意Offer!
- 前端專案重構的些許收穫前端
- 在創業型軟體公司的收穫創業
- 【GoLang 那點事】Go 指標,如此輕鬆掌握,希望有收穫Golang指標
- 做小遊戲要趟那些坑?手遊團隊轉型一年來的收穫與思考遊戲
- 給windows media初學者的一點建議 (轉)Windows
- 張一鳴:我的大學四年收穫及工作感悟
- 參加開源專案的一些經驗和收穫
- (C++伺服器學習筆記):報文多次收發轉為一次收發C++伺服器筆記
- 老男孩教育 | 28歲轉行學Linux,努力5個月,收穫年薪20w!Linux
- 獻給UNIX的初學者
- C++ Builder 初學問與答 (十一) (轉)C++UI
- C++ Builder 初學問與答 (十二) (轉)C++UI