欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言中g(shù)etchar()的原理以及易錯點(diǎn)解析

 更新時間:2022年03月03日 12:37:36   作者:66Kevin  
用getchar()函數(shù)讀取字符串時,字符串會存儲在輸入緩沖區(qū)中,包括輸入的回車字符,下面這篇文章主要給大家介紹了關(guān)于C語言中g(shù)etchar()的原理以及易錯點(diǎn)解析的相關(guān)資料,需要的朋友可以參考下

一.getchar()系列

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

工作原理:getchar()是stdio.h中的庫函數(shù),它的作用是從stdin流中讀入一個字符,也就是說,如果stdin有數(shù)據(jù)的話不用輸入它就可以直接讀取了,第一次getchar()時,確實(shí)需要人工的輸入,但是如果你輸了多個字符,以后的getchar()再執(zhí)行時就會直接從緩沖區(qū)中讀取了。

實(shí)際上是 輸入設(shè)備->內(nèi)存緩沖區(qū)->getchar()

你按的鍵是放進(jìn)緩沖區(qū)了,然后供程序getchar()

你有沒有試過按住很多鍵然后等一會兒會滴滴滴滴響,就是緩沖區(qū)滿了,你后頭按的鍵沒有存進(jìn)緩沖區(qū).

鍵盤輸入的字符都存到緩沖區(qū)內(nèi),一旦鍵入回車,getchar就進(jìn)入緩沖區(qū)讀取字符,一次只返回第一個字符作為getchar函數(shù)的值,如果有循環(huán)或足夠多的getchar語句,就會依次讀出緩沖區(qū)內(nèi)的所有字符直到’\n’.要理解這一點(diǎn),之所以你輸入的一系列字符被依次讀出來,是因?yàn)檠h(huán)的作用使得反復(fù)利用getchar在緩沖區(qū)里讀取字符,而不是getchar可以讀取多個字符,事實(shí)上getchar每次只能讀取一個字符.如果需要取消’\n’的影響,可以用getchar();來清除,這里getchar();只是取得了’\n’但是并沒有賦給任何字符變量,所以不會有影響,相當(dāng)于清除了這個字符.

作用1:從緩沖區(qū)讀走一個字符,相當(dāng)于清除緩沖區(qū)。

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

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

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

文章的源碼為:

#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,但是執(zhí)行到printf("input second char :\n");時,還沒等到第二次輸入就打印出來了。這是為什么??

原因:

其實(shí)在我們第一次輸入并按下回車的時候,控制臺一共獲得了四個字符,分別是:a、b、c、回車(enter)。但是因?yàn)閟canf()方法遇到非字符的時候會結(jié)束從控制臺的獲取,所以在輸入’abc’后,按下 ‘回車(enter)’ 的同時,將’abc’這個值以字符串的形式賦值給了類型為 ‘char’ 的 ‘m’ 數(shù)組,將使用過后的字符串: ‘回車(enter)’ 保存在控制臺輸入的緩沖區(qū),然后繼續(xù)執(zhí)行下一段輸出代碼,然后又要求用戶輸入。此時,因?yàn)樯弦淮伪皇褂眠^后的字符串被保存在緩沖區(qū),現(xiàn)在scanf()方法從控制臺的緩沖區(qū)獲取上一次被使用過后的字符串,并只截取第一個字符: ‘回車(enter)’ ,此時控制臺緩沖區(qū)才算使用完了。所以在看似被跳過的輸入,其實(shí)已經(jīng)scanf()方法已經(jīng)獲取了我們的輸入了,這個輸入就是一個 ‘回車(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()清理緩存

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

原因

在獲取用戶第一個輸入字符串時,scanf("%s",&m);,我們用%s作為轉(zhuǎn)換說明,%s的作用是“把輸入解釋成字符串。從第一個非空白字符開始,到下一個空白字符之前的所有字符都是輸入。”所以scanf把輸入的ab空格+回車就理解為ab+回車(ab后面沒有空格),但是依然以ab空格+回車的形式存儲在緩存區(qū)。我們輸入ab空格+回車,在緩存區(qū)是這樣存放的:

其中,第三格存放的為空格鍵。

當(dāng)程序運(yùn)行完 getchar();后,只清除了第三格中的空格鍵,因?yàn)橐淮螆?zhí)行getchar();只清除一個緩存,留下了第四格中的回車鍵,因此再次出現(xiàn)了同樣的問題。

解決問題:那么就是說只要運(yùn)行兩次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:

由此可見,當(dāng)我們第一次輸入ab空格+回車后,程序正常運(yùn)行。

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

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

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

解決方法:加入while循環(huán)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循環(huán)刪除緩存
        continue;
        
    printf("input second char :\n");        //提示用戶輸入第二個字符
    scanf("%c",&n);                         //獲取用戶的第二個字符
    printf("now you input second char is :%c\n",n);//輸出用戶輸入的第二個字符
    return 0;
    
}

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

解析:

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

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

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

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

第一步調(diào)用getchar()方法(這里getchar();只是取得了’\n’但是并沒有賦給任何字符變量,所以不會有影響,相當(dāng)于清除了這個字符)。

第二步判斷獲取到的緩存是否等于’\n’。

4.混合scanf()與getchar()

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

例:

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

#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:

我們發(fā)現(xiàn),在第一次輸入成功打印后,程序自動退出。這明顯不符合我們的題目要求。

原因是,輸入的c23其實(shí)是c23+換行符,scanf()函數(shù)把這個換行符留在了緩存中。getchar()不會跳過換行符,所以在進(jìn)入下一輪迭代時,還沒來得及輸入字符,它就讀取了換行符,然后將其賦值給了ch。而ch是換行符正式終止循環(huán)的條件。

如何改進(jìn)??

  1. 我們需要刪除scanf()函數(shù)留在緩存中的換行符即可。
  2. 在if語句中使用一個break語句,可以在scanf()的返回值不等于2時終止程序,即如果一個或兩個輸入值不是整數(shù)或者遇到文件結(jié)尾就終止程序。
#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()中轉(zhuǎn)化符的問題

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

原因:

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

總結(jié)

到此這篇關(guān)于C語言中g(shù)etchar()的原理以及易錯點(diǎn)解析的文章就介紹到這了,更多相關(guān)C語言 getchar()原理及易錯點(diǎn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • OpenCV+Qt實(shí)現(xiàn)圖像處理操作工具的示例代碼

    OpenCV+Qt實(shí)現(xiàn)圖像處理操作工具的示例代碼

    這篇文章主要介紹了利用OpenCV+Qt實(shí)現(xiàn)圖像處理操作工具,可以實(shí)現(xiàn)雪花屏、高斯模糊、中值濾波、毛玻璃等操作,感興趣的可以了解一下
    2022-08-08
  • C++初學(xué)者之根據(jù)輸入的任何一個正整數(shù),輸出可能被表示的連續(xù)正整數(shù)

    C++初學(xué)者之根據(jù)輸入的任何一個正整數(shù),輸出可能被表示的連續(xù)正整數(shù)

    這篇文章主要介紹了C++初學(xué)者之根據(jù)輸入的任何一個正整數(shù),輸出可能被表示的連續(xù)正整數(shù)的相關(guān)資料,需要的朋友可以參考下
    2016-03-03
  • 詳析C++中的auto

    詳析C++中的auto

    這篇文章主要介紹了詳析C++中的auto,auto是具有自動存儲器的局部變量,C++11中,標(biāo)準(zhǔn)委員會賦予了auto全新的含義即:auto不再是一個存儲類型指示符,而作為一個新的類型指示符來指示編譯器,下面來看看文章的詳細(xì)介紹吧
    2022-01-01
  • C++ Vector 動態(tài)數(shù)組的實(shí)現(xiàn)

    C++ Vector 動態(tài)數(shù)組的實(shí)現(xiàn)

    這篇文章主要介紹了C++ Vector 動態(tài)數(shù)組的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • C語言中浮點(diǎn)數(shù)的精度丟失問題解決

    C語言中浮點(diǎn)數(shù)的精度丟失問題解決

    大家好,本篇文章主要講的是C語言中浮點(diǎn)數(shù)的精度丟失問題解決,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2022-01-01
  • C++ 先對數(shù)組排序,在進(jìn)行折半查找

    C++ 先對數(shù)組排序,在進(jìn)行折半查找

    以下小編就為大家介紹兩種實(shí)現(xiàn)方法。第一種方法是,選擇排序法+循環(huán)折半查找法。第二種方法是,冒泡排序法+遞歸折半查找法。需要的朋友可以過來參考下,希望對大家有所幫助
    2013-10-10
  • C++中Digraphs、Trigraphs和Tokens的深入講解

    C++中Digraphs、Trigraphs和Tokens的深入講解

    這篇文章主要給大家介紹了關(guān)于C++中Digraphs、Trigraphs和Tokens的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用C++具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-09-09
  • 深入C++可見性與生命期的區(qū)別詳解

    深入C++可見性與生命期的區(qū)別詳解

    本篇文章對C++中可見性與生命期的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C語言實(shí)例真題講解數(shù)據(jù)結(jié)構(gòu)中單向環(huán)形鏈表

    C語言實(shí)例真題講解數(shù)據(jù)結(jié)構(gòu)中單向環(huán)形鏈表

    鏈表可以說是一種最為基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)了,而單向鏈表更是基礎(chǔ)中的基礎(chǔ)。鏈表是由一組元素以特定的順序組合或鏈接在一起的,不同元素之間在邏輯上相鄰,但是在物理上并不一定相鄰。在維護(hù)一組數(shù)據(jù)集合時,就可以使用鏈表,這一點(diǎn)和數(shù)組很相似
    2022-04-04
  • C語言字符串處理的驚天大坑問題解決

    C語言字符串處理的驚天大坑問題解決

    這篇文章主要為大家介紹了C語言字符串處理的驚天大坑問題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05

最新評論