日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言 getchar()原理及易错点解析

發布時間:2023/12/16 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言 getchar()原理及易错点解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 一.getchar()系列
    • 1.getchar()工作原理及作用
    • 2.使用getchar()清理回車\n
    • 3.使用getchar()清理緩存
    • 4.混合scanf()與getchar()

一.getchar()系列

1.getchar()工作原理及作用

  • 工作原理:getchar()是stdio.h中的庫函數,它的作用是從stdin流中讀入一個字符,也就是說,如果stdin有數據的話不用輸入它就可以直接讀取了,第一次getchar()時,確實需要人工的輸入,但是如果你輸了多個字符,以后的getchar()再執行時就會直接從緩沖區中讀取了。
    實際上是 輸入設備->內存緩沖區->getchar()
    你按的鍵是放進緩沖區了,然后供程序getchar()
    你有沒有試過按住很多鍵然后等一會兒會滴滴滴滴響,就是緩沖區滿了,你后頭按的鍵沒有存進緩沖區.
    鍵盤輸入的字符都存到緩沖區內,一旦鍵入回車,getchar就進入緩沖區讀取字符,一次只返回第一個字符作為getchar函數的值,如果有循環或足夠多的getchar語句,就會依次讀出緩沖區內的所有字符直到’\n’.要理解這一點,之所以你輸入的一系列字符被依次讀出來,是因為循環的作用使得反復利用getchar在緩沖區里讀取字符,而不是getchar可以讀取多個字符,事實上getchar每次只能讀取一個字符.如果需要取消’\n’的影響,可以用getchar();來清除,這里getchar();只是取得了’\n’但是并沒有賦給任何字符變量,所以不會有影響,相當于清除了這個字符.

  • 作用1:從緩沖區讀走一個字符,相當于清除緩沖區。

  • 作用2:前面的scanf()在讀取輸入時會在緩沖區中留下一個字符’\n’(輸入完按回車鍵所致),所以如果不在此加一個getchar()把這個回車符取走的話,接下來的scanf()就不會等待從鍵盤鍵入字符,而是會直接取走這個“無用的”回車符,從而導致讀取有誤。

2.使用getchar()清理回車\n

這個問題轉載自n_s_X14,但是作者在文章最后留了一個問題,現在在這里給大家解釋一下原因。

文章的源碼為:

#include <stdio.h>int main(void){char m[40];char n;printf("please input first str:\n"); //提示用戶輸入第一個字符串scanf("%s",m); //獲取用戶第一個輸入字符串printf("you input str is :%s\n",m); //輸出用戶的輸入的第一個字符串printf("input second char :\n"); //提示用戶輸入第二個字符scanf("%c",&n); //獲取用戶的第二個字符printf("now you input second char is :%c\n",n);//輸出用戶輸入的第二個字符return 0;}

Output:

please input first str: abc you input str is :abc input second char : now you input second char is :Program ended with exit code: 0

問題:我們第一次輸入abc后成功打印出來了you input str is :abc,但是執行到printf("input second char :\n");時,還沒等到第二次輸入就打印出來了。這是為什么??

原因:

其實在我們第一次輸入并按下回車的時候,控制臺一共獲得了四個字符,分別是:a、b、c、回車(enter)。但是因為scanf()方法遇到非字符的時候會結束從控制臺的獲取,所以在輸入’abc’后,按下 ‘回車(enter)’ 的同時,將’abc’這個值以字符串的形式賦值給了類型為 ‘char’ 的 ‘m’ 數組,將使用過后的字符串: ‘回車(enter)’ 保存在控制臺輸入的緩沖區,然后繼續執行下一段輸出代碼,然后又要求用戶輸入。此時,因為上一次被使用過后的字符串被保存在緩沖區,現在scanf()方法從控制臺的緩沖區獲取上一次被使用過后的字符串,并只截取第一個字符: ‘回車(enter)’ ,此時控制臺緩沖區才算使用完了。所以在看似被跳過的輸入,其實已經scanf()方法已經獲取了我們的輸入了,這個輸入就是一個 ‘回車(enter)’ 。

解決問題:
使用getchar()方法,清除掉abc后面的緩存(回車enter)。

#include <stdio.h>int main(void){char m[40];char n;printf("please input first str:\n"); //提示用戶輸入第一個字符串scanf("%s",m); //獲取用戶第一個輸入字符串printf("you input str is :%s\n",m); //輸出用戶的輸入的第一個字符串getchar();printf("input second char :\n"); //提示用戶輸入第二個字符scanf("%c",&n); //獲取用戶的第二個字符printf("now you input second char is :%c\n",n);//輸出用戶輸入的第二個字符return 0;}

Output:

please input first str: abc you input str is :abc input second char : de now you input second char is :d Program ended with exit code: 0

3.使用getchar()清理緩存

文章結束時留了一個問題:如果在第一次輸入ab后加一個空格再回車,又會出現原來的問題,即程序只輸出了ab后就自動跳過下一次的輸入之間退出了,控制臺輸出如下圖所示。

原因

  • 在獲取用戶第一個輸入字符串時,scanf("%s",&m);,我們用%s作為轉換說明,%s的作用是“把輸入解釋成字符串。從第一個非空白字符開始,到下一個空白字符之前的所有字符都是輸入。”所以scanf把輸入的ab空格+回車就理解為ab+回車(ab后面沒有空格),但是依然以ab空格+回車的形式存儲在緩存區
  • 我們輸入ab空格+回車,在緩存區是這樣存放的:
    其中,第三格存放的為空格鍵。
    當程序運行完 getchar();后,只清除了第三格中的空格鍵,因為一次執行getchar();只清除一個緩存,留下了第四格中的回車鍵,因此再次出現了同樣的問題。
  • 解決問題:那么就是說只要運行兩次getchar();,清除掉第三格和第四格就可以正常了。

    #include <stdio.h>int main(void){char m[40];char n;printf("please input first str:\n"); //提示用戶輸入第一個字符串scanf("%s",m); //獲取用戶第一個輸入字符串printf("you input str is :%s\n",m); //輸出用戶的輸入的第一個字符串getchar(); //第一次清除緩存getchar(); //第二次清除緩存printf("input second char :\n"); //提示用戶輸入第二個字符scanf("%c",&n); //獲取用戶的第二個字符printf("now you input second char is :%c\n",n);//輸出用戶輸入的第二個字符return 0;}

    Output:

    由此可見,當我們第一次輸入ab空格+回車后,程序正常運行。

    進一步:如果我們輸入的是a空格b+回車,scanf("%s",m); 這一步只能讀取到a,因為a后面有空格。但是a空格b+回車在緩沖區這樣存放:

    因此,如果想要程序正常運行則需要在輸出用戶的輸入的第一個字符串后加入三次getchar();操作,即刪除掉第二,第三,第四格的內容。

    問題:如果我們輸入a空格bbbbbbbb+回車,那可能需要無數個getchar();來清除緩存,這時應該怎么辦??

    解決方法:加入while循環while(getchar()!='\n') continue;

    #include <stdio.h>int main(void){char m[40];char n;printf("please input first str:\n"); //提示用戶輸入第一個字符串scanf("%s",m); //獲取用戶第一個輸入字符串printf("you input str is :%s\n",m); //輸出用戶的輸入的第一個字符串while(getchar()!='\n') //通過while循環刪除緩存continue;printf("input second char :\n"); //提示用戶輸入第二個字符scanf("%c",&n); //獲取用戶的第二個字符printf("now you input second char is :%c\n",n);//輸出用戶輸入的第二個字符return 0;}

    這時,我們輸入a空格bbbbbbbb+回車,程序正常運行。

    解析:

    while(getchar()!='\n')continue;

    可以看出這段代碼代替了無數個getchar(),他的作用是跳過剩余的輸入行

    第一次while循環消除第二格緩存,第二次while循環消除第三格緩存……直到第八次。最后一次同樣,getchar()也消除了回車。

    while(getchar()!='\n')可以拆分成兩步,

    • 第一步調用getchar()方法(這里getchar();只是取得了’\n’但是并沒有賦給任何字符變量,所以不會有影響,相當于清除了這個字符)。
    • 第二步判斷獲取到的緩存是否等于’\n’。

    4.混合scanf()與getchar()

    假設程序要求用getchar()處理字符輸入,用scanf()處理數值輸入,這兩個函數都能很好的完成任務,但是不能混合使用因為getchar()讀取每個字符,包括空格、制表符和換行符;而scanf()在讀取數字時則會跳過空格、制表符和換行符。

    例:
    要求用戶輸入一個字母和兩個數字,輸出以第一個數字為行數,第二個數字為列數,以字母為內容的數列,要求可以不斷輸入直至鍵入回車退出程序:

    #include <stdio.h> void display(char cr,int lines,int width); int main(int argc, const char * argv[]) {int ch;int rows,cols;printf("Enter a character and two integers:\n");while((ch=getchar())!= '\n'){scanf("%d %d", &rows,&cols);display(ch, rows, cols);printf("Enter another character and two integers;\n");printf("Enter a newline to quit.\n");}printf("Bye.\n");return 0;} void display(char cr,int lines,int width){int row,col;for(row=1; row<= lines; row++){for(col =1; col<=width; col++){putchar(cr);}putchar('\n');} }

    output:

    我們發現,在第一次輸入成功打印后,程序自動退出。這明顯不符合我們的題目要求。
    原因是,輸入的c23其實是c23+換行符,scanf()函數把這個換行符留在了緩存中。getchar()不會跳過換行符,所以在進入下一輪迭代時,還沒來得及輸入字符,它就讀取了換行符,然后將其賦值給了ch。而ch是換行符正式終止循環的條件。

    如何改進??

  • 我們需要刪除scanf()函數留在緩存中的換行符即可。
  • 在if語句中使用一個break語句,可以在scanf()的返回值不等于2時終止程序,即如果一個或兩個輸入值不是整數或者遇到文件結尾就終止程序。
  • #include <stdio.h> void display(char cr,int lines,int width); int main(int argc, const char * argv[]) {int ch;int rows,cols;printf("Enter a character and two integers:\n");while((ch=getchar())!= '\n'){if( scanf("%d %d", &rows,&cols)!=2 ){break;}display(ch, rows, cols);while(getchar()!='\n'){continue;}printf("Enter another character and two integers;\n");printf("Enter a newline to quit.\n");}printf("Bye.\n");return 0;} void display(char cr,int lines,int width){int row,col;for(row=1; row<= lines; row++){for(col =1; col<=width; col++){putchar(cr);}putchar('\n');} }

    Output:


    題外話:

    scanf()中轉化符的問題


    問題:從上面兩張圖片中可以看出,當scanf("%d",&c);改為scanf("%c",&c);時,控制臺中出現了圖二的問題。character為什么為空白??

    原因:
    如果格式是%c,那么任何字符都是它想要的,所以第二個程序中的第二個scanf("%c")會得到‘+’后面的空格’ '。如果格式是%d,則會忽略任何空白字符(空格、回車、制表符等),忽略的意思是,從緩沖區里刪除,但并不保存;如果遇到數字,則拿出并保存給后面的整數,也就是說%d的時候,scanf想要的字符是數字和空白符。所以第一個程序里的第二個scanf("%d")忽略掉了空格,正確輸入了數字。

    總結

    以上是生活随笔為你收集整理的C语言 getchar()原理及易错点解析的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。