【C语言的秘密】密探—深究C语言中多组输入的秘密!

news2024/11/20 9:26:25

场景引入:

         你是否在刷题过程中,经常遇到以下场景呢?

场景一:

场景二:

从这些题上都能看见输入描述中提出了一条多组输入,那啥是多组输入?如何实现它呢?

多组输入:在输入数据时,有多组数据需要分别处理的情况

接下来探究如何利用循环实现它。

如果还有不会循环的小伙伴可以看我之前写的一篇文章:初阶C语言-分支与循环结构-CSDN博客


📚常用的输入函数的介绍

📖字符类

📝getchar(字符输入函数,包含头文件stdio.h即可使用)

getchar
int getchar (void)

可用cplusplus官网查找到函数原型如下:

📌函数讲解

函数名                         getchar

函数的参数                  void

函数的返回类型            int

1.成功读取到字符则返回字符的ASCII码值

2.读取失败则返回EOF(-1)   

选择EOF右击鼠标找到转到定义选项,点击。

可发现,EOF就是#define定义的常量,它的值就是-1,EOF的意思是the end of file,文件末尾标志。

💌举例:

#include <stdio.h>

int main()
{
	int ch;
	ch = getchar();

	return 0;
}

☑️getchar函数的作用是从标准输入流读取(获得)一个字符,可以简单的理解为接收键盘输入的一个字符。这里我是从键盘输入字符a,可以看见ch这个变量存储的就是字符a对应的ASCII码值97

💌举例:

☑️这里我输入的是2,但是getchar会默认把我输入的2当做字符,输出字符2对应的ASCII码值50赋值给ch。

🤔如果输入字符串或者多位数的整数会有啥结果?

😶只会取第一个读到的字符。

📝putchar(字符输出函数,包含头文件stdio.h即可使用)

putchar
int putchar (int character)

📌函数讲解

函数名                       putchar

函数的参数                int character

函数的返回类型         int 

1.成功读取到字符则返回字符的ASCII码值,并在屏幕上输出读取到的字符

2.读取失败则返回EOF(-1)

💌举例:

#include <stdio.h>

int main()
{
	int ch;
	int a;
	ch = getchar();
	a = putchar(ch);

	return 0;
}

☑️第一个a是我输入给getchar函数,第二个a是程序执行到putchar函数,在屏幕上(终端)上打印的字符a。ch接收了getchar函数的返回值,a接受了putchar函数的返回值,这里都是字符a对应的ASCII码值97。

📝字符类的多组输入

💌举例:设置一个程序,只有当输入的字符为数字时才将其输出

#include <stdio.h>

int main()
{
	int ch;
	while ((ch = getchar()) != EOF)
	{
		if (ch >= '0' && ch <= '9')
		{
			putchar(ch);
			printf("\n");//单纯打印一个字符换个行,方便观察
		}
	}

	return 0;
}

☑️多组输入按control+z+回车即可退出。

💌举例:场景一

#include <stdio.h>

int main()
{
	int ch;
	while ((ch = getchar()) != EOF)
	{
		if (ch >= 'A' && ch <= 'Z')//大写字母
			putchar(ch + 32);
		else if (ch >= 'a' && ch <= 'z')//小写字母
			putchar(ch - 32);
		printf("\n");//换行方便观察
	}

	return 0;
}

☑️大小写字母的ASCII码值之间相差了32。

🤔思考:同样是换行方便观察,为啥输出结果是这样呢?

😶事实上你输入的是字母然后按了个回车(ASCII码值是10),回车是转义字符'\n',等于你输入了两个字符。

☑️细心的你会发现上一个例题是满足条件才printf("\n"),而这次是经过一次循环就会进行一次printf("\n")。

改进:

#include <stdio.h>

int main()
{
	int ch;
	while ((ch = getchar()) != EOF)
	{
		if (ch >= 'A' && ch <= 'Z')//大写字母
		{
			putchar(ch + 32);
			printf("\n");
		}
		else if (ch >= 'a' && ch <= 'z')//小写字母
		{
			putchar(ch - 32);
			printf("\n");
		}
	}

	return 0;
}

📖万能类

📝scanf(包含头文件stdio.h即可使用)

💌举例:

#include <stdio.h>

int main()
{
	char password[20];
	printf("请输入密码:");
	scanf("%s", password);//数组名就是地址,可以不加&
	printf("请确认你的密码:(Y/N)");
	int ch = getchar();
	if (ch == 'Y')
		printf("确认成功\n");
	else
		printf("确认失败\n");

	return 0;
}

🤔思考:为啥都没有让我输入Y/N就确认失败了呢?

😶输入缓冲区的引入

注:因为getchar读到的是缓冲区内的字符'\n'(回车),故出现了bug。

改进:在引入一个getchar读走\n,这个操作叫做清空缓冲区。

#include <stdio.h>

int main()
{
	char password[20];
	printf("请输入密码:");
	scanf("%s", password);//数组名就是地址,可以不加&
	printf("请确认你的密码:(Y/N)");
	getchar();//处理掉缓冲区的\n
	int ch = getchar();
	if (ch == 'Y')
		printf("确认成功\n");
	else
		printf("确认失败\n");

	return 0;
}

其他清理缓存区的办法:

使用gets函数代替scanf函数接收字符串的输入

#include <stdio.h>

int main()
{
	char password[20];
	printf("请输入密码:");
	gets(password);
	printf("请确认你的密码:(Y/N)");
	int ch = getchar();
	if (ch == 'Y')
		printf("确认成功\n");
	else
		printf("确认失败\n");

	return 0;
}

gets函数还会顺带把缓冲区的\n一起带走。

🤔思考:若是读取整数的函数需要单独处理掉缓冲区的\n吗?

😶不需要,因为\n不是整数不会被读取。

📝scanf函数的多组输入

#include <stdio.h>

int main()
{
	char arr[20];
	while (scanf("%s", arr) != EOF)
	{
		printf("%s\n", arr);
	}

	return 0;
}

注:按三次control+z+回车即可退出多组输入。可以思考一下为啥这次不需要清空缓冲区。

可见scanf函数读取时以空格或者回车作为一次读取结束标志,当是循环时,输入空格分隔开的一串字符串会被识别为两串字符串。

若要对scanf输入字符串中就是含有空格可使用以下格式:

scanf("%[^\n]", arr);
#include <stdio.h>

int main()
{
	char arr[20];
	scanf("%[^\n]", arr);
	{
		printf("%s\n", arr);
	}

	return 0;
}

#include <stdio.h>

int main()
{
	char arr[20];
	while (scanf("%[^\n]", arr) != EOF)
	{
		printf("%s\n", arr);
	}

	return 0;
}

比较可惜的是这样会死循环,因为这种格式带不走缓冲区的内容,他只是把\n之前的字符拷贝一份放到了arr中,所以缓冲区一直有abcd abc,所以死循环了。

改进:

#include <stdio.h>

int main()
{
	char arr[20];
	while (scanf("%[^\n]", arr) != EOF)
	{
		printf("%s\n", arr);
		int ch;
		while ((ch = getchar()) != EOF && ch != '\n')//清空缓冲区
		{
			;
		}
	}

	return 0;
}

注:按两次control + z +回车即可退出多组输入。

📚总结

        本节介绍了多组输入以及相关输入函数,如何清空(输入)缓冲区的一些方法。在进行多组输入时,尤其使用能读取字符,字符串的函数时,小心未清理缓冲区而产生bug。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1225612.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Centos(Linux)服务器安装Dotnet8 及 常见问题解决

1. 下载dotnet8 sdk 下载 .NET 8.0 SDK (v8.0.100) - Linux x64 Binaries 拿到 dotnet-sdk-8.0.100-linux-x64.tar.gz 文件 2. 把文件上传到 /usr/local/software 目录 mkdir -p /usr/local/software/dotnet8 把文件拷贝过去 mv dotnet-sdk-8.0.100-linux-x64.tar.gz /usr/loc…

【Linux】 uptime命令使用

uptime 正常运行时间提供以下信息的单行显示。当前时间、系统运行的时间、当前登录的用户数量以及过去1、5和15分钟的系统平均负载。 语法 uptimeuptime命令 -Linux手册页 作者 由Larry Greenfield编写和迈克尔K约翰逊编写。 命令选项及作用 执行令 man uptime 执行命令结…

【linux】进行间通信——共享内存+消息队列+信号量

共享内存消息队列信号量 1.共享内存1.1共享内存的原理1.2共享内存的概念1.3接口的认识1.4实操comm.hppservice.cc &#xff08;写&#xff09;clint.cc &#xff08;读&#xff09; 1.5共享内存的总结1.6共享内存的内核结构 2.消息队列2.1原理2.2接口 3.信号量3.1信号量是什么3…

goland 远程调试 remote debug

1、远程服务器装好go环境&#xff0c;并设置国内源 linux go安装 参考&#xff1a; 如何在 Debian / Ubuntu 上安装 Go 开发环境 - 知乎 设置国内源 go env -w GOPROXYhttps://goproxy.cn,direct 2、远程服务器安装dlv git clone https://github.com/derekparker/delve.gi…

移动端表格分页uni-app

使用uni-app提供的uni-table表格 网址&#xff1a;https://uniapp.dcloud.net.cn/component/uniui/uni-table.html#%E4%BB%8B%E7%BB%8D <uni-table ref"table" :loading"loading" border stripe type"selection" emptyText"暂无更多数据…

C++ STL之string初始

我最近开了几个专栏&#xff0c;诚信互三&#xff01; > |||《算法专栏》&#xff1a;&#xff1a;刷题教程来自网站《代码随想录》。||| > |||《C专栏》&#xff1a;&#xff1a;记录我学习C的经历&#xff0c;看完你一定会有收获。||| > |||《Linux专栏》&#xff1…

2023年【陕西省安全员B证】考试报名及陕西省安全员B证模拟试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年陕西省安全员B证考试报名为正在备考陕西省安全员B证操作证的学员准备的理论考试专题&#xff0c;每个月更新的陕西省安全员B证模拟试题祝您顺利通过陕西省安全员B证考试。 1、【多选题】《陕西省建设工程质量和…

【计算机组成原理】知识点巩固 - 存储器概述

目录 1、存储器分类 1.1、按存储介质分类 1.2、按存取方式分类 1.3、按信息的可改写性分类 1.4、按信息的可保存性分类 1.5、按功能和存取速度分类 2、存储器技术指标 2.1、存储容量 2.2、存取速度 3、存储系统层次结构 4、主存的基本结构 5、主存中数据的存放 5…

基于SSM+Vue的鲜花销售系统/网上花店系统

基于SSM的鲜花销售系统/网上花店系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringMyBatisSpringMVC工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 主页 管理员界面 摘要 鲜花销售系统是一个基于SSM&#xff08;Spring …

springboot项目中没有识别到yml文件解决办法

springboot项目中没有识别到yml文件解决办法 ![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传] 1、这个意思就是没有配置数据库的数据源路径。所以需要配置数据源&#xff0c;比如mysql的驱动和路径。检查是否在properties或者yml文件中是否已经配置好。…

75基于matlab的模拟退火算法优化TSP(SA-TSP),最优路径动态寻优,输出最优路径值、路径曲线、迭代曲线。

基于matlab的模拟退火算法优化TSP(SA-TSP)&#xff0c;最优路径动态寻优&#xff0c;输出最优路径值、路径曲线、迭代曲线。数据可更换自己的&#xff0c;程序已调通&#xff0c;可直接运行。 75matlab模拟退火算法TSP问题 (xiaohongshu.com)

python django 小程序博客源码

开发工具&#xff1a; PyCharm&#xff0c;mysql5.7&#xff0c;微信开发者工具 技术说明&#xff1a; python django html 小程序 功能介绍&#xff1a; 用户端&#xff1a; 登录注册&#xff08;含授权登录&#xff09; 首页显示搜索文章&#xff0c;文章分类&#xf…

持续集成交付CICD:Jenkins通过API触发流水线

目录 一、理论 1.HTTP请求 2.调用接口的方法 3.HTTP常见错误码 二、实验 1.Jenkins通过API触发流水线 三、问题 1.如何拿到上一次jenkinsfile文件进行自动触发流水线 一、理论 1.HTTP请求 &#xff08;1&#xff09;概念 HTTP超文本传输协议&#xff0c;是确保服务器…

linux如何使用shell远程连接

简介&#xff1a;本文的一切条件基于redhat的linux操作系统。 1、创建虚拟机&#xff1a; 如有需要&#xff0c;请转至【linux基础】在VMware上安装RHEL9详细教程_融社的博客-CSDN博客 &#xff08;如若侵权&#xff0c;该篇立删&#xff09; 2、使用命令查看网段信息 打…

Android——Gradle插件项目根目录settings.gradle和build.gradle

一、settings.gradle结构分析 项目根目录下的settings.gradle配置文件示例&#xff1a; pluginManagement {/*** The pluginManagement.repositories block configures the* repositories Gradle uses to search or download the Gradle plugins and* their transitive depen…

gRPC 四模式之 双向流RPC模式

双向流RPC模式 在双向流 RPC 模式中&#xff0c;客户端以消息流的形式发送请求到服务器端&#xff0c;服务器端也以消息流的形式进行响应。调用必须由客户端发起&#xff0c;但在此之后&#xff0c;通信完全基于 gRPC 客户端和服务器端的应用程序逻辑。 为什么有了双向流模式…

Codeforces Round #909 (Div. 3)

A. Game with Integers 签到题&#xff0c;但是本蒟蒻11分钟才AC&#xff0c;主要还是英文题面不熟练&#xff0c;题目中加粗了after&#xff0c;只有下一步操作之后能被整除才胜利。 英文题面的加粗单词很重要&#xff0c;注意提高签到题速度。 B. 250 Thousand Tons of TNT…

leetcoe刷题日志-6N字形变换

将一个给定字符串 s 根据给定的行数 numRows &#xff0c;以从上往下、从左到右进行 Z 字形排列。 比如输入字符串为 “PAYPALISHIRING” 行数为 3 时&#xff0c;排列如下&#xff1a; 之后&#xff0c;你的输出需要从左往右逐行读取&#xff0c;产生出一个新的字符串&#…

【数据结构】图的存储结构(邻接矩阵)

一.邻接矩阵 1.图的特点 任何两个顶点之间都可能存在边&#xff0c;无法通过存储位置表示这种任意的逻辑关系。 图无法采用顺序存储结构。 2.如何存储图&#xff1f; 将顶点与边分开存储。 3.邻接矩阵&#xff08;数组表示法&#xff09; 基本思想&#xff1a; 用一个一维数…

公共字段自动填充-Mybatis Plus实现

简历描述 使用ThreadLocal动态获取当前登录用户&#xff0c;从而解决MybatisPlus公共字段自动填充问题。达到简化编码的目的&#xff0c;使业务方法更加简洁。 问题分析 前面我们已经完成了后台系统的员工管理功能的开发&#xff0c;在新增员工时需要设置创建时间、创建人、…