----------------------------------------------------
| 問題描述一:(分析scanf()和getchar()讀取字符)? |
--------------------------------------------------
scanf(), getchar()等都是標(biāo)準(zhǔn)輸入函數(shù)宣蔚,一般人都會(huì)覺得這幾個(gè)函數(shù)非常簡單帆喇,沒什么特殊的糕韧。但是有時(shí)候卻就是因?yàn)槭褂眠@些函數(shù)除了問題,卻找不出其中的原因。下面先看一個(gè)很簡單的程序:
程序1:
? ? ? ? int main()
? ? ? ? {
? ? ? ? ? ? ? char ch1, ch2;
? ? ? ? ? ? ? scanf("%c", &ch1);
? ? ? ? ? ? ? scanf("%c", &ch2);
? ? ? ? ? ? ? printf("%d? %d\n", ch1, ch2);
? ? ? ? ? ? ? return 0;
? ? ? ? }
程序2:
? ? ? ? int main()
? ? ? ? {
? ? ? ? ? ? ? char ch1, ch2;
? ? ? ? ? ? ? ch1 = getchar();
? ? ? ? ? ? ? ch2 = getchar();
? ? ? ? ? ? ? printf("%d? %d\n", ch1, ch2);
? ? ? ? ? ? ? return 0;
? ? ? ? }
? 程序的本意很簡單儡羔,就是從鍵盤讀入兩個(gè)字符程癌,然后打印出這兩個(gè)字符的ASCII碼值。可是執(zhí)行程序后會(huì)發(fā)現(xiàn)除了問題:當(dāng)從鍵盤輸入一個(gè)字符后莉钙,就打印出了 結(jié)果廓脆,根本就沒有輸入第二個(gè)字符程序就結(jié)束了。例如用戶輸入字符'a', 打印結(jié)果是97磁玉,10停忿。這是為什么呢?
【分析】:
? ? 首先我們呢看一下輸入操作的原理蚊伞, 程序的輸入都建有一個(gè)緩沖區(qū)席赂,即輸入緩沖區(qū)。一次輸入過程是這樣的时迫,當(dāng)一次鍵盤輸入結(jié)束時(shí)會(huì)將輸入的數(shù)據(jù)存入輸入緩沖區(qū)颅停,而cin函數(shù)直接從輸入緩沖區(qū)中 取數(shù)據(jù)。正因?yàn)閏in函數(shù)是直接從緩沖區(qū)取數(shù)據(jù)的掠拳,所以有時(shí)候當(dāng)緩沖區(qū)中有殘留數(shù)據(jù)時(shí)癞揉,cin函數(shù)會(huì)直接取得這些殘留數(shù)據(jù)而不會(huì)請求鍵盤輸入,這就是例子 中為什么會(huì)出現(xiàn)輸入語句失效的原因碳想!
? ? 其實(shí)這里的10恰好是回車符烧董!這是因?yàn)閟canf()和getchar()函數(shù)是從輸入流緩沖區(qū)中讀取值的,而并非從鍵盤(也就是終端)緩沖區(qū)讀取胧奔。而讀 取時(shí)遇到回車(\n)而結(jié)束的逊移,這個(gè)\n會(huì)一起讀入輸入流緩沖區(qū)的,所以第一次接受輸入時(shí)取走字符后會(huì)留下字符\n龙填,這樣第二次的讀入函數(shù)直接從緩沖區(qū)中 把\n取走了胳泉,顯然讀取成功了,所以不會(huì)再從終端讀妊乙拧扇商!這就是為什么這個(gè)程序只執(zhí)行了一次輸入操作就結(jié)束的原因!
----------------------------------------------------
|? 問題描述二:(分析scanf()和gets()讀取字符串)? |
----------------------------------------------------
首先我們看一下scanf()讀取字符串的問題:
程序3:
? ? ? ? int main()
? ? ? ? {
? ? ? ? ? ? ? char str1[20], str2[20];
? ? ? ? ? ? ? scanf("%s",str1);
? ? ? ? ? ? ? printf("%s\n",str1);? ?
? ? ? ? ? ? ? scanf("%s",str2);?
? ? ? ? ? ? ? printf("%s\n",str2);?
? ? ? ? ? ? ? return 0;
? ? ? ? }
程序的功能是讀入一個(gè)字符串輸出宿礁,在讀入一個(gè)字符串輸出案铺。可我們會(huì)發(fā)現(xiàn)輸入的字符串中不能出現(xiàn)空格梆靖,例如:
測試一輸入:
Hello world!
輸出:
Hello
world!
【分 析】到此程序執(zhí)行完畢控汉,不會(huì)執(zhí)行第二次的讀取操作!這個(gè)問題的原因跟問題一類似返吻,第一次輸入Hello world!后姑子,字符串Hello world!都會(huì)被讀到輸入緩沖區(qū)中,而scanf()函數(shù)取數(shù)據(jù)是遇到回車测僵、空格街佑、TAB就會(huì)停止,也就是第一個(gè)scanf()會(huì)取出"Hello", 而"world!"還在緩沖區(qū)中沐旨,這樣第二個(gè)scanf會(huì)直接取出這些數(shù)據(jù)森逮,而不會(huì)等待從終端輸入。
測試二:
Hello[Enter]
Hello[輸出]
world[Enter]
world[輸出]
【分析】程序執(zhí)行了兩次從鍵盤讀入字符串磁携,說明第一次輸入結(jié)束時(shí)的回車符被丟棄吊宋!即:scanf()讀取字符串會(huì)舍棄最后的回車符!
我們再看一下gets()讀取字符串的情況:
用scanf來讀取一個(gè)字符串時(shí)颜武,字符串中是不可以出現(xiàn)空格的,一旦出現(xiàn)空格拖吼,后面的數(shù)據(jù)就會(huì)舍棄殘留在緩沖區(qū)中鳞上。其實(shí)有另外一個(gè)函數(shù)是可以接受空格的,那就是gets()吊档,下面我們看一下這個(gè)函數(shù)的應(yīng)用篙议,我們把程序3改動(dòng)一下:
? ? int main()
? ? {
? ? ? ? ? char str1[20], str2[20];
? ? ? ? ? gets(str1);
? ? ? ? ? printf("%s\n",str1);? ?
? ? ? ? ? gets(str2);?
? ? ? ? ? printf("%s\n",str2);?
? ? ? ? ? return 0;
? ? }
【分析】顯然與上一個(gè)程序的執(zhí)行情況不同,這次程序執(zhí)行了兩次從鍵盤的讀入怠硼,而且第一個(gè)字符串取了Hello world! 接受了空格符鬼贱,而沒有像上一個(gè)程序那樣分成了兩個(gè)字符串!所以如果要讀入一個(gè)帶空格符的字符串時(shí)因該用gets(), 而不宜用scanf()!
--------------------------------------------------------
| 問題描述三:(getchar()暫停程序香璃,查看程序執(zhí)行結(jié)果)|
--------------------------------------------------------
? ? 不知道大家有沒有遇到過這樣的問題这难,有的編譯器程序執(zhí)行完后的結(jié)果界面不會(huì)停下而是一閃就沒了,以至于看不到執(zhí)行結(jié)果葡秒。所以很多人在程序最后加上 getchar()語句姻乓,目的是想讓程序執(zhí)行完后停下來,等待從終端接收一個(gè)字符再結(jié)束程序眯牧√Q遥可是發(fā)現(xiàn)有時(shí)候這樣根本沒用,程序照樣跳出去了学少。這是為什么 呢剪个?
【分析】原因跟上面例子講的一樣,是因?yàn)檩斎刖彌_區(qū)中還有數(shù)據(jù)版确,所以getchar()會(huì)成果讀到數(shù)據(jù)扣囊,所以就跳出了!
------------------
|? 【總結(jié)】? |
------------------
第一:要注意不同的函數(shù)是否接受空格符阀坏、是否舍棄最后的回車符的問題!
讀取字符時(shí):
scanf()以Space如暖、Enter、Tab結(jié)束一次輸入忌堂,不會(huì)舍棄最后的回車符(即回車符會(huì)殘留在緩沖區(qū)中)盒至;
getchar()以Enter結(jié)束輸入,也不會(huì)舍棄最后的回車符;
讀取字符串時(shí):
scanf()以Space枷遂、Enter樱衷、Tab結(jié)束一次輸入
gets()以Enter結(jié)束輸入(空格不結(jié)束),接受空格酒唉,會(huì)舍棄最后的回車符矩桂!
第二:為了避免出現(xiàn)上述問題,必須要清空緩沖區(qū)的殘留數(shù)據(jù)痪伦,可以用以下的方法解決:
方法1:C語言里提供了函數(shù)清空緩沖區(qū)侄榴,只要在讀數(shù)據(jù)之前先清空緩沖區(qū)就沒問題了!
? ? ? 這個(gè)函數(shù)是fflush(stdin)网沾。
方法2:自己取出緩沖區(qū)里的殘留數(shù)據(jù)癞蚕。
(說實(shí)話這個(gè)語句我也沒看懂,呵呵辉哥!為什么格式控制是這樣的桦山!希望高手指點(diǎn)一下!)
? ? ? scanf("%[^\n]",string);
————————————————
版權(quán)聲明:本文為CSDN博主「zqixiao_09」的原創(chuàng)文章醋旦,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議恒水,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/zqixiao_09/article/details/50189477