“C語言“——scanf()、getchar() 、putchar()、之間的關系

scanf函數說明

scanf函數是對來自于標準輸入流的輸入數據作格式轉換,并將轉換結果保存至format后面的實參所指向的對象。

而const char*format 指向的字符串為格式控制字符串,它指定了可輸入的字符串以及賦值時轉換方法。

簡單來說給一個打印格式(輸入數據格式),scanf函數會將打印數據格式的結果轉換放到后面的實參變量當中。

比如下面的代碼

#include<stdio.h>
int main()
{int a = 0;char ch = 0;double b = 0.0;scanf("%d %c %lf", &a, &ch, &b);printf("%d %c %lf", a, ch, b);return 0;
}

但scanf函數有一個缺點,就是scanf讀取不了空格和回車等字符,當scanf讀到這兩個字符時,scanf會讀取失敗返回EOF,如果匹配錯誤也會讀取失敗返回EOF(比如應該是%d的數據轉換到了char實參變量當中)。

EOF

EOF全名是:End of File 在<stdio.h>頭文件中被定義為負值,即-1。

EOF的值不同編譯器下值不同,在VS2019是-1?

如果沒有將頭文件<stdio.h>包含到程序中,那么EOF就沒有定義,程序不能編譯和運行。

getchar和putchar

putchar的返回值是int,因為字符在程序存儲的是ASCII碼值,而且putchar只能打印字符,不能打印字符串,就是配合getchar()使用的。如果putchar成功獲取了字符就返回所寫字符,失敗就返回EOF。

#include<stdio.h>
int main()
{putchar('a');putchar('b');putchar('c');return 0;
}

getchar返回也是int,參數是void,可有可無,getchar是從標準輸入流讀取字符(空格 回車都可以讀取)并將其返回,如果讀取失敗就返回EOF。?

比如

#include<stdio.h>
int main()
{int ch;while ((ch = getchar()) != EOF){putchar(ch);}return 0;
}

getchar如果緩沖區沒有字符,getchar會等待我們的輸入且摁下回車鍵才會打印在屏幕上。

配合putchar使用。

?按下回車鍵后才在屏幕上輸出對應字符。

?ctrl+Z是將程序結束掉,退出了程序終止了代碼循環。

crtl+Z相當于EOF。

?為什么按回車鍵才會將字符輸出到屏幕上呢?

?C語言的輸入輸出一般會將讀入的字符以及待輸出的字符暫時保存在緩存中(緩沖區),當達到以下條件才進行實際的輸入輸出操作。

1.緩存已滿 2.輸入換行符(\n)? 3.立即輸出

對應方式稱為1.全緩沖 2.行緩沖 3,無緩沖

鍵盤輸入的內容不會直接給cpu處理打印在屏幕上 而是交給緩存 提高cpu運行效率。

getchar與scanf的關系

我們根據下圖代碼來分析getchar和scanf之間的關系

#include<stdio.h>
int main()
{char password[20] = { 0 };printf("請輸入密碼:>");scanf("%s", password);printf("請確認密碼正確Y/N:>");char ch = 0;scanf("%c", &ch);if ('Y' == ch){printf("密碼正確\n");}else{printf("密碼錯誤\n");}return 0;
}

?當程序運行時,我們剛輸入完密碼程序直接結束了,都沒有確定密碼的正確性,這是為什么呢?

當我們輸入密碼摁下回車鍵時,在緩沖區輸入了1234\n,回車鍵相當于換行等于轉義字符\n

第一個scanf讀取了1234 第二個scanf讀取了\n 直接填滿了兩個scanf的嘴巴,因此直接程序結束

并且結果為密碼錯誤,當我們輸入完1234摁下回車鍵那刻\n也被載入到了緩沖區,第二個scanf

定睛一看緩沖區有內容直接就讀取走了。

解決辦法?

?這時我們就要請出getchar給scanf擦屁股了,因為getchar能讀取回車 空格等字符。

#include<stdio.h>
int main()
{char password[20] = { 0 };printf("請輸入密碼:>");scanf("%s", password);printf("請確認密碼正確Y/N:>");char ch = 0;getchar();scanf("%c", &ch);if ('Y' == ch){printf("密碼正確\n");}else{printf("密碼錯誤\n");}return 0;
}

但如果有人在設置密碼時寫入了空格,而且scanf讀取不了空格和回車字符,這時還是會出現代碼判斷錯誤導致運行結果錯誤。

我們直接用while循環搞一個一勞永逸的解決方案

直接使用循環清空緩沖區的空格 回車等字符

#include<stdio.h>
int main()
{char password[20] = { 0 };printf("請輸入密碼:>");scanf("%s", password);printf("請確認密碼正確Y/N:>");char ch = 0;while ((getchar()) != '\n'){;}
//以下兩種寫法都okscanf("%c",&ch);//ch=getchar();if ('Y' == ch){printf("密碼正確\n");}else{printf("密碼錯誤\n");}return 0;
}

?關系

輸入b后摁下回車鍵形成\n

緩沖區載入的就是b\n

第一個scanf讀取b 第二個scanf讀取\n? 因此程序結束語在第三行

輸入a\n

scanf讀取a getchar讀取\n putchar輸出a?

?輸入a\n 第一個scanf讀走a? getchar讀走\n

第二個scanf正常使用再次輸入b\n? putchar在下一行輸出b

scanf讀走as \nbxx是putchar讀取的? ?a是第二個scanf讀取的后面還有個\n

所以程序結束語在第4行。

總結

如果scanf輸入過程中遇到空格 回車鍵等字符,scanf自己處理不了的讀取字符時,就用getchar來解決,如果有多個處理不了的特殊字符就用while循環來處理(scanf處理不了的空格 回車鍵等特殊字符),配合getchar和putchar來給scanf的正常使用(擦屁股)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/536799.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/536799.shtml
英文地址,請注明出處:http://en.pswp.cn/news/536799.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【并發編程篇】源碼分析,手動創建線程池

文章目錄 &#x1f6f8;前言&#x1f339;Executors的三大方法 &#x1f354;簡述線程池&#x1f386;手動創建線程池?源碼分析?代碼實現&#xff0c;手動創建線程池&#x1f388;CallerRunsPolicy()&#x1f388;AbortPolicy()&#x1f388;DiscardPolicy()&#x1f388;Dis…

LNPMariadb數據庫分離|web服務器集群

LNP&Mariadb數據庫分離&#xff5c;web服務器集群 網站架構演變單機版LNMP獨立數據庫服務器web服務器集群與Session保持 LNP與數據庫分離1. 準備一臺獨立的服務器&#xff0c;安裝數據庫軟件包2. 將之前的LNMP網站中的數據庫遷移到新的數據庫服務器3. 修改wordpress網站配置…

2023.12.24 關于 Redis 中 String 類型內部編碼 及 應用場景

目錄 String 類型內部編碼 3 種內部編碼方式 String 類型應用場景 Cache 緩存 鍵名命名規則 計數&#xff08;Counter&#xff09; 共享會話&#xff08;Session &#xff09; 手機驗證碼 總結 String 類型內部編碼 3 種內部編碼方式 int&#xff1a;用來表示 64 位 —…

vue3菜單權限管理實現

前提 你的菜單是根據路由動態生成的&#xff0c;具體可以參考這篇博客對el-menu組件進行遞歸封裝&#xff08;根據路由配置動態生成&#xff09; 描述 首先將路由分為常量路由constantRoute&#xff08;所有用戶都有的路由&#xff09;和異步路由asyncRoute&#xff08;需要動…

Gradle 插件

自定義Gradle插件 - 簡書

小天使的小難題:新生兒疝氣的關注與溫馨呵護

引言&#xff1a; 新生兒疝氣是一種在出生后可能出現的常見情況&#xff0c;雖然通常不會造成長期影響&#xff0c;但對于家長而言&#xff0c;了解如何正確應對新生兒疝氣是至關重要的。本文將深入探討新生兒疝氣的原因、癥狀&#xff0c;以及家長在面對這一問題時應該采取的…

1224. 交換瓶子(藍橋杯/圖論)

題目&#xff1a; 1224. 交換瓶子 - AcWing題庫 輸入樣例1&#xff1a; 5 3 1 2 5 4輸出樣例1&#xff1a; 3輸入樣例2&#xff1a; 5 5 4 3 2 1輸出樣例2&#xff1a; 2 思路&#xff1a;圖論 1.將對應的位置與當前的瓶子序列相連形成環。 2.最少交換次數能形成的最多…

Vue中的事件委托(事件代理)使用方法介紹

事件委托&#xff08;事件代理&#xff09; 將原本需要綁定在子元素上的事件監聽器委托在父元素上&#xff0c;讓父元素充當事件監聽的職務。 事件委托是一種利用事件冒泡的特性&#xff0c;在父節點上響應事件&#xff0c;而不是在子節點上響應事件的技術。它能夠改善性能&a…

如何理解JDK、JRE、JVM區別與聯系

摘要&#xff1a;JDK是 Java 語言的軟件開發工具包(SDK)。在JDK的安裝目錄下有一個jre目錄&#xff0c;里面有兩個文件夾bin和lib&#xff0c;在這里可以認為bin里的就是jvm&#xff0c;lib中則是jvm工作所需要的類庫&#xff0c;而jvm和 lib合起來就稱為jre。 一、JDK JDK(Ja…

【【迭代16次的CORDIC算法-verilog實現】】

迭代16次的CORDIC算法-verilog實現 -32位迭代16次verilog代碼實現 CORDIC.v module cordic32#(parameter DATA_WIDTH 8d32 , // we set data widthparameter PIPELINE 5d16 // Optimize waveform)(input …

第十四章Java博客

lambda就是數學中的“λ”的讀音&#xff0c;lambda表達式是基于λ演算而得名的&#xff0c;因為lambda抽象&#xff08;lambda abstraction&#xff09;表示一個匿名的函數&#xff0c;于是開發語言也將lambda表達式用來表示匿名函數&#xff0c;也就是沒有函數名字的函數。C#…

maven管理工具使用package打包的時候無法將lib文件夾下的第三方jar包打入,上線打jar包后運行異常問題

問題描述&#xff1a; 調用第三方接口的時候通過手動引入了第三方的兩個jar包到我本項目的lib文件夾下&#xff0c;并在pom文件添加入下配置&#xff1a; <dependency><groupId>cn.xxxx.xxxx.core</groupId><artifactId>xxxx-core</artifactId>…

Spring Boot 中實現跨域的幾種方式

前言 在現代Web應用中&#xff0c;由于安全性和隱私的考慮&#xff0c;瀏覽器限制了從一個域向另一個域發起的跨域HTTP請求。解決這個問題的一種常見方式是實現跨域資源共享&#xff08;CORS&#xff09;。Spring Boot提供了多種方式來處理跨域請求&#xff0c;本文將介紹其中的…

C語言字符串處理提取時間(ffmpeg返回的時間字符串)

【1】需求 需求&#xff1a;有一個 “00:01:33.90” 這樣格式的時間字符串&#xff0c;需要將這個字符串的時間值提取打印出來&#xff08;提取時、分、秒、毫秒&#xff09;。 這個時間字符串從哪里來的&#xff1f; 是ffmpeg返回的時間&#xff0c;也就是視頻的總時間。 下…

vs快捷鍵

ctrlMo 折疊代碼塊 ctrlML 打開代碼塊

電子電器架構(E/E)演化 —— 主流主機廠域集中架構概述

電子電器架構(E/E)演化 —— 主流主機廠域集中架構概述 我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 屏蔽力是信息過載時代一個人的特殊競爭力,任何消耗你的人和事,多看一眼都是你的不對。…

系列七(實戰)、發送 接收單向消息(Java操作RocketMQ)

一、發送 & 接收單向消息 1.1、概述 發送單向消息&#xff0c;適用于發送方不關心或者不在意消息的發送結果&#xff0c;這種方式的吞吐量很大&#xff0c;但是存在消息丟失的風險&#xff0c;對于重要消息要慎用&#xff01;該種方式通常適用于對消息沒有那么嚴格的場景中…

類和對象的創建和實例化

1. 類的概述 1.1 具體示例 類是描述一類事物的特征和行為的統稱&#xff0c;抽象的不存在的&#xff0c;泛指的概念&#xff0c;例如&#xff1a;描述一個人&#xff0c;從外觀上&#xff08;特征&#xff09;和言行舉止&#xff08;行為&#xff09;上進行描述外觀上&#xff…

c 語言學習:輸出階乘的算式

c 語言學習&#xff1a;輸出階乘的算式 代碼 #include "stdio.h"int fact(int num){if (num < 1){printf("1 ");return 1;} else {printf("%d x ",num);return num * fact(num-1);} }int main(){int num 10; // printf("plz inpu…

【華為OD題庫-107】編碼能力提升計劃-java

題目 為了提升軟件編碼能力&#xff0c;小王制定了刷題計劃&#xff0c;他選了題庫中的n道題&#xff0c;編號從0到n-1&#xff0c;并計劃在m天內按照題目編號順序刷完所有的題目(注意&#xff0c;小王不能用多天完成同一題) 在小王刷題計劃中&#xff0c;小王需要用time[i]的時…