網站首頁 編程語言 正文
getchar的使用
1.從緩沖區讀走一個字符,相當于清除緩沖區 ?
2.前面的scanf()在讀取輸入時會在緩沖區中留下一個字符'\n'(輸入完s[i]的值后按回車鍵所致),所以如果不在此加一個getchar()把這個回車符取走的話,gets()就不會等待從鍵盤鍵入字符,而是會直接取走這個“無用的”回車符,從而導致讀取有誤 ?
3. ?
getchar()是在輸入緩沖區順序讀入一個字符(包括空格、回車和Tab) ?
getchar()使用不方便,解決方法: ??
(1)使用下面的語句清除回車: ??
while(getchar()!='\n'); ??
(2)用getche()或getch()代替getchar(),其作用是從鍵盤讀入一個字符(不用按回車),注意要包含頭文件<conio.h> ?
4.?
getchar()是stdio.h中的庫函數,它的作用是從stdin流中讀入一個字符,也就是說,如果stdin有數據的話不用輸入它就可以直接讀取了,第一次getchar()時,確實需要人工的輸入,但是如果你輸了多個字符,以后的getchar()再執行時就會直接從緩沖區中讀取了。 ?
實際上是 輸入設備->內存緩沖區->程序getchar ? ?
你按的鍵是放進緩沖區了,然后供程序getchar ? ?
你有沒有試過按住很多鍵然后等一會兒會滴滴滴滴響,就是緩沖區滿了,你后頭按的鍵沒有存進緩沖區. ? ?
鍵盤輸入的字符都存到緩沖區內,一旦鍵入回車,getchar就進入緩沖區讀取字符,一次只返回第一個字符作為getchar函數的值,如果有循環或足夠多的getchar語句,就會依次讀出緩沖區內的所有字符直到'\n'.要理解這一點,之所以你輸入的一系列字符被依次讀出來,是因為循環的作用使得反復利用getchar在緩沖區里讀取字符,而不是getchar可以讀取多個字符,事實上getchar每次只能讀取一個字符.如果需要取消'\n'的影響,可以用getchar();來清除,這里getchar();只是取得了'\n'但是并沒有賦給任何字符變量,所以不會有影響,相當于清除了這個字符.還要注意的是這里你在鍵盤上輸入ssss看到的回顯正是來自于getchar的作用,如果用getch就看不到你輸入了什么.
1、首先,我們看一下這段代碼:
它的簡單意思就是從鍵盤讀入一個字符,然后輸出到屏幕。理所當然,我們輸入1,輸出就是1,輸入2,輸出就是2。
那么我們如果輸出的是12呢?
它的輸出是1。
這里我們先簡單的解釋下,因為當我們從鍵盤輸入字符‘1’,‘2’,并按下回車后,我們的輸入被放入了輸入緩沖區,這個時候getchar()會從緩沖區中讀取我們剛才的輸入,一次只讀一個字符,所以字符1就被拿出來了,賦值給了c,然后putchar()又將c放在了標準輸出,也就是這里的屏幕,所以我們看見了最終的顯示結果1。同時字符‘1’也被緩沖區釋放了,而字符‘2’仍然被留在了緩沖區。而這樣是很不安全的,有可能下次使用的時候,我們的緩沖區會讀到一些垃圾,但是當程序結束的時候,它會自動刷新。
2、我們接著看下面的代碼:
大家覺得這幾行代碼是什么意思呢?大家是否真的看懂了呢?
如果你覺得你看懂了,那么我提一個問題,你覺得是不是你從鍵盤輸入一個字符就會輸出一個字符,直到遇見了換行符呢?
emmmmm。
如果你真的這么想了,那你就錯了。
它真正的運行過程應該是這樣的:還記得我們剛才說過的東西嗎,getchar()會從輸入緩沖區去讀取內容,也就是說我們把所有的內容都輸入完成并且按下了Enter鍵后,我們的輸入才被送進去了輸入緩沖區,這個時候,while循環才開始工作,每一次getchar()從輸入緩沖區讀取一個字符,然后如果不是換行符就輸出。
3、那么我們為什么要使用緩沖區呢?
舉個例子,我們知道計算機CPU的處理速度很快的,而我們鍵盤的輸入速度總是比不過CPU的處理速度,那么CPU就得一直等著鍵盤輸入完,這樣很浪費資源。于是,我們黨鍵盤輸入完了,再讓CPU一次性處理,這樣就會大大地提高效率。
又比如,我們的打印機打印文檔,打印機的處理速度是很慢的,所以我們會將文檔輸出到打印機的緩存中去,這樣打印機就可以自行慢慢打印,而不必占用CPU資源。
4、緩沖區的類型
緩沖區 分為三種類型:全緩沖、行緩沖和不帶緩沖。
1、全緩沖
在這種情況下,當填滿標準I/O緩存后才進行實際I/O操作。全緩沖的典型代表是對磁盤文件的讀寫。
2、行緩沖
在這種情況下,當在輸入和輸出中遇到換行符時,執行真正的I/O操作。這時,我們輸入的字符先存放在緩沖區,等按下回車鍵換行時才進行實際的I/O操作。典型代表是鍵盤輸入數據。
3、不帶緩沖
也就是不進行緩沖,標準出錯情況stderr是典型代表,這使得出錯信息可以直接盡快地顯示出來。
5、緩沖區的刷新
緩沖區會在以下三種情況下被刷新:
1、緩沖區滿
2、執行flush刷新緩沖區的語句
3、程序正常結束。
首先,用getchar()函數進行字符的輸入,并不是直接從鍵盤這個硬件中讀取輸入的字符,而是從“輸入緩沖區”中得到的字符。
輸入緩沖區是一個字符的隊列,其中存儲了所有你尚未讀取的字符。
每次調用getchar函數,它就會從輸入緩沖區中讀出第一個字符,并把這個字符從輸入緩沖區中清除。
然而,這個輸入緩沖區的設計,是把所有從鍵盤上輸入的東西都放進去的,包括你每次按的回車符‘\n’,
而getchar函數只讀走了你在回車前輸入的那個字符,而將回車符保留在了輸入緩沖區中。
于是,第二次調用getchar時,函數就從輸入緩沖區中讀出了'\n'。
要解決這個問題,有兩種可行的途徑。
一是多加一個getchar(),過濾掉回車,但是這種方法有不足,就是如果你在調用第一個getchar時輸入了多個字符,
那么,加入一個getchar并不能把所有未讀取的字符過濾。如果你的本意是重新從“鍵盤”讀取的話,最好是加一個
fflush(stdin);
清除輸入緩沖區
擴展知識:
C語言】getchar 函數的正確使用
一、getchar 函數
從上面的介紹來看,我們要正確使用getchar函數,首先得了解什么是緩沖區。
二、緩沖區
1、什么是緩沖區
緩沖區又稱為緩存,它是內存空間的一部分。
也就是說,在內存空間中預留了一定的存儲空間,這些存儲空間用來緩沖輸入或輸出的數據,這部分預留的空間就叫做緩沖區。
緩沖區根據其對應的是輸入設備輸出設備,分為輸入緩沖區和輸出緩沖區。
2、為什么要存在緩沖區
我們為什么要引入緩沖區呢?
比如我們從磁盤里取信息,我們先把讀出的數據放在緩沖區,計算機再直接從緩沖區中取數據,等緩沖區的數據取完后再去磁盤中讀取,這樣就可以減少磁盤的讀寫次數,再加上計算機對緩沖區的操作大大快于對磁盤的操作,故應用緩沖區可大大提高計算機的運行速度。
又比如,我們使用打印機打印文檔,由于打印機的打印速度相對較慢,我們先把文檔輸出到打印機相應的緩沖區,打印機再自行逐步打印,這時我們的CPU可以處理別的事情。現在您基本明白了吧,緩沖區就是一塊內存區,它用在輸入輸出設備和CPU之間,用來緩存數據。它使得低速的輸入輸出設備和高速的CPU能夠協調工作,避免低速的輸入輸出設備占用CPU,解放出CPU,使其能夠高效率工作。
3、緩沖區的類型
緩沖區分為三種類型:全緩沖、行緩沖和不帶緩沖。
1、全緩沖
在這種情況下,當填滿標準I/O緩存后才進行實際I/O操作。全緩沖的典型代表是對磁盤文件的讀寫。
2、行緩沖
在這種情況下,當在輸入和輸出中遇到換行符時,執行真正的I/O操作。這時,我們輸入的字符先存放在緩沖區,等按下回車鍵換行時才進行實際的I/O操作。典型代表是鍵盤輸入數據。
3、不帶緩沖
也就是不進行緩沖,標準出錯情況stderr是典型代表,這使得出錯信息可以直接盡快地顯示出來。
4、緩沖區的刷新
以下四種情況會引發緩沖區刷新:
- 緩沖區滿時;
- 執行 flush 語句;
- 執行 endl 語句;
- 關閉文件。
三、getchar 函數的正確使用
1、getchar 的換行問題
我們來觀察下面這段代碼
#include<stdio.h>
int main()
{
int ch = 0;
while ((ch = (getchar())) != EOF)
{
putchar(ch);
}
return 0;
}
我們可以看到我們每次從鍵盤輸入一個字符并回車后,putchar輸出時會自動換行,就是因為我們每次除了輸入字符外,還敲了一個回車,而這個回車會被存儲在緩沖區中,當我們用getchar讀取字符時,會從緩沖區中依次逐個讀取所有的字符(包括換行、空格、Tab),直到緩沖區中沒有數據,每讀取一個字符就用putchar打印一下,所以這里會自動換行。
^Z:Ctrl+Z,輸入后會被認定為EOF,從而來結束循環(VS中有些時候要重復按三次才會結束循環,其他編譯器都是按一次)。
2、getchar 與 scanf 的混合使用
我們來觀察下面這段代碼:
#include<stdio.h>
int main()
{
char password[20] = { 0 };
printf("請輸入密碼:>");
scanf("%s", password);
printf("請確認密碼(Y/N):>");
int ch = getchar();
if (ch == 'Y')
{
printf("確認成功\n");
}
else
{
printf("確認失敗\n");
}
return 0;
}
我們可以看到程序并沒有等待我們輸入Y/N來確認密碼,而是直接結束,原因就是我們緩沖區中存放的是abcdef\n,而scanf函數是遇到空格、換行符(\n)、Tab時結束,所以\n并沒有被讀取走,而是繼續留在了緩沖區中,而當getchar讀取數據時發現緩沖區中并不為空,所以直接讀取了\n,然后判斷if條件,結束程序,而不會等待我們輸入Y/N。
那么要如何避免這種情況發生呢?有兩種方法:
法一:在scanf后面加一個getchar(不推薦)
#include<stdio.h>
int main()
{
char password[20] = { 0 };
printf("請輸入密碼:>");
scanf("%s", password);
getchar(); //讀取剩下的\n
printf("請確認密碼(Y/N):>");
int ch = getchar();
if (ch == 'Y')
{
printf("確認成功\n");
}
else
{
printf("確認失敗\n");
}
return 0;
}
我們在scanf函數后面加上一個getchar函數,用于清空緩沖區里面多余的\n,但是這種方法有弊端,不推薦使用,具體弊端如下:
如圖:我們從鍵盤輸入abcd ef,我們可以看到,程序并沒有等待我們輸入Y/N,而是直接執行if語句,這是因為 scanf函數遇到空格、換行符(\n)、Tab時會停止讀取,所以緩沖區中剩下的字符是_ef\n,一次getchar無法清空緩沖區。所以說,法一只能解決一部分情況,想要徹底解決scanf緩沖區殘留的問題需要用到法二。
法二:在scanf后面加 while( getchar() != ‘\n’) 語句(推薦)
#include<stdio.h>
int main()
{
char password[20] = { 0 };
printf("請輸入密碼:>");
scanf("%s", password);
getchar(); //讀取剩下的\n
printf("請確認密碼(Y/N):>");
while (getchar() != '\n')
{
;
}
int ch = getchar();
if (ch == 'Y')
{
printf("確認成功\n");
}
else
{
printf("確認失敗\n");
}
return 0;
}
程序中的while( getchar() != ‘\n’)語句會不斷讀取緩沖區中的字符,直到把\n讀取走,從而達到清空緩沖區的目的。
原文鏈接:https://blog.csdn.net/qq_30464257/article/details/80841574
相關推薦
- 2022-10-07 關于pyqt5彈出提示框的詳細介紹_python
- 2023-03-02 Kotlin關于協程是什么的探究_Android
- 2022-07-16 new FileOutputStream(“data\\test2.txt“,true),true是
- 2022-10-18 一文詳解Python中的Map,Filter和Reduce函數_python
- 2024-07-18 Spring Security之配置體系
- 2022-10-22 C#中的屬性解析(get、set、value)_C#教程
- 2022-12-05 關于adfuller函數返回值的參數說明與記錄_python
- 2022-10-01 react使用useState修改對象或者數組的值無法改變視圖的問題_React
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支