網站首頁 編程語言 正文
前言
近期我在重新學習C語言時候,我發現了一個嚴重的問題,getchar我居然不會用了....也不是說不會用,我發現了一個非常讓我困惑想不明白的問題。可能我在第一次接觸C語言時候,就沒有把這個概念弄清楚吧,以至于現在會不明白。
getchar困惑的點
我利用getchar函數輸入了一串字符ABCD,然后把這串字符給到ch,然后緊接著我打印這個ch,然后我得到了一個字符A,看到這里大家沒有感覺有什么問題對吧,當然沒有問題,因為getchar只會讀一個字符,自然就只讀到了A,然后打印時候也自然而然就只打印了這個A出來。
好的我們接著往下看
看到這個我不知道大家有沒有想到一個問題,反正我當時就是因為這個問題所困惑很久的。
首先通過第一個例子,我們知道了,getchar是只會讀取一個字符
可是這個例子呢,我輸入了一串字符ABCDE,按理說他也只是讀取到一個字符,那就是這串字符中的第一個字符A,然后讀取到了之后把它給了變量ch, 然后來判斷這個ch等不等于EOF。
EOF是文件結束標志,在鍵盤上也就是ctrl+z 大家可以自己打印一下然后對照ASCII碼看一下
很顯然,當前這個里面根本就沒有ctrl+z,所以條件為真,然后執行打印語句。
根據上面我們那段分析,然后應該打印一個字符A對嗎,疑惑的事情發生了,它打印了ABCDE!!!是的,完完整整打印出來了。
可能大家經常見到這個類似程序,然后習以為常了,都覺得是應該完完整整打印出來
好的,講到這里大家是不是就覺得很困惑了,為什么會這樣呢?
那我現在就好好給大家講一下了,原來這里面還涉及到了一個概念
緩沖區
緩沖區又稱為緩存,它是內存空間的一部分。也就是說,在內存空間中預留了一定的存儲空間,這些存儲空間用來緩沖輸入或輸出的數據,這部分預留的空間就叫做緩沖區。
那么這個和我們的getchar又有什么聯系呢?
當然有聯系,當我們調用了getchar函數時候,這個函數內部其實是這樣做的:
他此時會先從緩存區中讀一遍,此時讀完之后發現,緩存區中沒有數據,他就會等待外部輸入,光標此時就會一閃一閃的~?
當我們外部輸入了字符之后,然后我們就會敲回車結束,這時候我們輸入的字符其實就直接全部存在了緩存區中。
假設我此時輸入了字符ABCD,然后回車結束,然后此時緩存區中就有了ABCD\n
注意,有意思的事情來了,還有\n ???哈哈哈哈接著往下看
緩沖區帶來的問題
大家仔細看一下有沒有發現,為什么我getchar沒有輸入字符呢??
其實不是我沒有輸入字符,只是在我輸入完scanf的字符之后,回車結束這個scanf的輸入,然后奇怪的事情發生了,程序就直接結束了,是的,跳過了getchar輸入字符這個過程。
大家有沒有覺得奇怪?
這就是我剛才上面給大家提到的 \n
是這樣的,當我此時調用了scanf函數之后,我外部輸入了 ABCD,然后輸入完ABCD之后呢我要結束輸入,然后我們就會去敲回車,注意!!這個回車其實也是一個字符,然后他也會連同我前面輸入的ABCD一起放到緩存區,也就是說此時緩存區中就有了ABCD\n?
我們做一個小小的測試就知道了
看到這個打印的結果,大家明白了吧
getchar工作原理
原來調用getchar函數的時候,它其實是直接從緩存區中讀,如果緩存區中有數據,他就會直接拿走第一個,然后他的使命也就結束了。其實這里呢就是上面scanf在緩存區中拿走了ABCD,然后還剩下一個 10,這個10其實是\n ,是它在ASCII碼中的表示。于是這個剩下的\n就在緩存區中存下去了,然后他此時遇到了getchar函數,然后getchar在緩存區中讀,發現:誒,還剩一個\n,那么我就直接拿走,然后他的使命也就便結束了,所以就出現了不會等待我們外部輸入的那種情況了。
那么我們可以解決這個問題嗎?
解決緩沖區帶來的問題之清空緩存區
明白了緩沖區和getchar的聯系之后,其實我們想解決就很好辦了
我們只需要在getchar讀取之前在插入一個getchar函數,也就是說讓他在下一次真正getchar讀取之前,我們先再用一個getchar函數讀一下那個緩存區剩下的\n,這樣下一次我們真正的getchar讀取時候,緩存區就空了。
好了getchar的工作原理我們徹底明白了,那么我們在回到最初的那個疑惑上面。?
解決最初的困惑
第一次循環:首先緩存區為空,光標閃爍,然后等待我的輸入
我輸入了一個字符A,然后我繼續輸入了回車結束,那么我此時其實輸入了兩個字符,一個字符A,一個字符 \n,此時他們都被存放在了緩存區。然后緩存區有了數據之后,光標此時不在閃爍,getchar函數便開始直接讀取,然后在這一次循環中,getchar函數讀取到了一個字符A,然后將它給到ch,然后條件表達式為真(不等于ctrl+z),所以執行打印ch,然后打印出了一個字符A。
第二次循環:這時候緩存區還殘留了一個\n,光標不閃爍,getchar也不會等待外部輸入
那么此時getchar直接讀取到這個緩存區中的\n,繼續給到ch,然后表達式還是為真,所以繼續打印這個ch,此時因為ch已經是被換掉了\n,所以打印換行,光標位置發生改變。
第三次循環:緩存區為空,getchar讀取不到數據,光標閃爍,getchar等待外部輸入數據。
至此我們在接著往下看
?第一次循環:緩存區為空,getchar讀取不到緩存區的數據,于是光標閃爍,getchar等待外部輸入數據。
此時我輸入了一串ABC,然后回車結束輸入。此時緩存區中便有了字符ABCD\n,然后getchar讀取第一個字符A,然后將它給到ch,然后條件表達式為真,打印了ch,于是第一個A就出來了。
第二次循環:緩存區還剩余BC\n,getchar直接讀取
此時getchar讀取到字符B,然后給到ch,條件表達式為真,繼續打印ch,此時便得到了AB。
第三次循環:緩存區還剩余C\n,getchar直接讀取
然后還是一樣getchar讀取到C,然后給到ch,之后表達式為真,打印出來了ch,然后經過這一次循環就得到了ABC
第四次循環:緩存區還剩余一個\n,最后打印這個\n,于是光標下一行。
最終結果就得到了ABC
然后我再次輸入 ctrl+Z
于是緩存區存在了ctrl+z(EOF),然后getchar去讀取,然后給到ch,然后表達式判斷,條件為假,ch==EOF,所以循環跳出,程序結束。
總結
getchar函數是直接從緩存區中讀取數據,如果緩存區中有數據,則直接讀取第一個數據,如果沒有數據,那么就光標閃爍,等待外部輸入數據。
要非常注意的是,我們其他地方輸入的回車也會被存在緩存區當成一個字符,然后后面getchar也會將其直接讀出,在這個地方很容易出錯!!
原文鏈接:https://blog.csdn.net/m0_58384187/article/details/122495096
相關推薦
- 2022-12-07 一文帶你搞懂C語言動態內存管理_C 語言
- 2022-03-15 使用jib-maven-plugin插件打包docker鏡像上傳到私有鏡像庫,為了賬戶安全,需要設置
- 2022-04-09 Spring Boot 配置CROS Filter
- 2022-07-12 Springboot Druid 啟動報錯:Failed to configure a DataSo
- 2022-07-22 git倉庫的第一次上傳以及修改上傳項目
- 2022-04-17 docker 執行python腳本 并查看日志
- 2022-04-09 Windows 環境配置Github 的SSH key
- 2024-01-28 springboot登錄認證JWT令牌
- 最近更新
-
- 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同步修改后的遠程分支