“C语言“——scanf()、getchar() 、putchar()、之间的关系

2023-12-26 05:45

本文主要是介绍“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的正常使用(擦屁股)。

这篇关于“C语言“——scanf()、getchar() 、putchar()、之间的关系的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/538309

相关文章

从基础到高级详解Go语言中错误处理的实践指南

《从基础到高级详解Go语言中错误处理的实践指南》Go语言采用了一种独特而明确的错误处理哲学,与其他主流编程语言形成鲜明对比,本文将为大家详细介绍Go语言中错误处理详细方法,希望对大家有所帮助... 目录1 Go 错误处理哲学与核心机制1.1 错误接口设计1.2 错误与异常的区别2 错误创建与检查2.1 基础

Go语言中json操作的实现

《Go语言中json操作的实现》本文主要介绍了Go语言中的json操作的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录 一、jsOChina编程N 与 Go 类型对应关系️ 二、基本操作:编码与解码 三、结构体标签(Struc

Java 中的 equals 和 hashCode 方法关系与正确重写实践案例

《Java中的equals和hashCode方法关系与正确重写实践案例》在Java中,equals和hashCode方法是Object类的核心方法,广泛用于对象比较和哈希集合(如HashMa... 目录一、背景与需求分析1.1 equals 和 hashCode 的背景1.2 需求分析1.3 技术挑战1.4

python语言中的常用容器(集合)示例详解

《python语言中的常用容器(集合)示例详解》Python集合是一种无序且不重复的数据容器,它可以存储任意类型的对象,包括数字、字符串、元组等,下面:本文主要介绍python语言中常用容器(集合... 目录1.核心内置容器1. 列表2. 元组3. 集合4. 冻结集合5. 字典2.collections模块

基于Go语言开发一个 IP 归属地查询接口工具

《基于Go语言开发一个IP归属地查询接口工具》在日常开发中,IP地址归属地查询是一个常见需求,本文将带大家使用Go语言快速开发一个IP归属地查询接口服务,有需要的小伙伴可以了解下... 目录功能目标技术栈项目结构核心代码(main.go)使用方法扩展功能总结在日常开发中,IP 地址归属地查询是一个常见需求:

GO语言短变量声明的实现示例

《GO语言短变量声明的实现示例》在Go语言中,短变量声明是一种简洁的变量声明方式,使用:=运算符,可以自动推断变量类型,下面就来具体介绍一下如何使用,感兴趣的可以了解一下... 目录基本语法功能特点与var的区别适用场景注意事项基本语法variableName := value功能特点1、自动类型推

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

Go语言连接MySQL数据库执行基本的增删改查

《Go语言连接MySQL数据库执行基本的增删改查》在后端开发中,MySQL是最常用的关系型数据库之一,本文主要为大家详细介绍了如何使用Go连接MySQL数据库并执行基本的增删改查吧... 目录Go语言连接mysql数据库准备工作安装 MySQL 驱动代码实现运行结果注意事项Go语言执行基本的增删改查准备工作

Springboot项目构建时各种依赖详细介绍与依赖关系说明详解

《Springboot项目构建时各种依赖详细介绍与依赖关系说明详解》SpringBoot通过spring-boot-dependencies统一依赖版本管理,spring-boot-starter-w... 目录一、spring-boot-dependencies1.简介2. 内容概览3.核心内容结构4.

Go语言使用Gin处理路由参数和查询参数

《Go语言使用Gin处理路由参数和查询参数》在WebAPI开发中,处理路由参数(PathParameter)和查询参数(QueryParameter)是非常常见的需求,下面我们就来看看Go语言... 目录一、路由参数 vs 查询参数二、Gin 获取路由参数和查询参数三、示例代码四、运行与测试1. 测试编程路