scanf老是出错?带你详细解决输入缓冲区问题

这篇具有很好参考价值的文章主要介绍了scanf老是出错?带你详细解决输入缓冲区问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.前言

我们一般在进行输入输出的时候,就会用到 scanf / printf并且根据格式指定可以输入输出各种类型的数据。可以输入整形,字符,浮点型等其他类型的数据。

今天呢我先给大家再介绍一下 getchar 和 putchar.

2.getchar 和 putchar

getchar呢是读取一个字符,并且只能读取一个字符。putchar呢则是输出一个字符。

我们要学习getchar 和 putchar也很简单

  • 首先getchar获取一个字符后会返回过来,我们就定义一个整形变量 ch 来接收它,然后再用putchar把接收的值打印出来即可。
int main()
{
	int ch = getchar();
	putchar(ch);

	return 0;
}

scanf老是出错?带你详细解决输入缓冲区问题

  • 可能有人会问 getchar返回类型为什么是 int 类型,不是 char 类型。
  • 因为getchar读到字符后,它会把字符的ASCLL码值返回来。所以用整形接收
  • 还有一个点,getchar这个函数正常读取到字符的时候返回的是字符的ASCLL码值,但是它读取失败时返回的是 EOF,也就是 -1(整形)。整形的接收最好用int。ASCLL码的范围是 0 ~ 127
  • 大家可以通过这个网站搜索各种函数cplusplus.com
    scanf老是出错?带你详细解决输入缓冲区问题

3.缓冲区问题

3.1先观察一个代码

我们先来看一个代码:

这串代码的意思就是读取一个字符,然后输出一个字符。如果没有读取失败,就一直进行循环读取。 按ctrl+z即可停下来。

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

scanf老是出错?带你详细解决输入缓冲区问题

3.2输入缓冲区

上面这个代码看似很简单,其实逻辑是很复杂的。

我给大家介绍下它是怎样工作的:

  • 当我们第一次运行的时候,它会等待让我们进行输入。
  • 大家注意:像 getchar 和 scanf 是让我们输入数据的,但是这个输入数据是从键盘上拿吗?其实并不是。其实中间存在一个输入缓冲区。

scanf老是出错?带你详细解决输入缓冲区问题

  • getchar 和 scanf 首先去看输入缓冲区中有没有东西存在当我们第一次读取的时候去看输入缓冲区里没有东西,怎么办呢?这个时候就需要我们从键盘输入数据到我们的缓冲区里面
  • 第一次我们向输入缓冲区输入了一个A,并按下 回车键。回车其实就是 \n。第一次 getchar 把A读走,然后putchar把它输出。但是第二次进入循环,输入缓冲区中存在一个 \n,而 \n 不等于EOF,所以getchar就把 \n读走了,putchar 输出的时候就进行了一次换行。

3.3清除缓冲区

上面介绍的有什么用呢,其实它的用处还蛮多的。一般可以用来清空缓冲区。

看个代码:

  • 这个代码就是让我们输入密码,并判断密码对不对。若密码正确,则输入Y。
int main()
{
	printf("请输入密码:>");
	char password[20] = { 0 };
	scanf("%s", password);
	printf("请确认密码(Y/N):>");
	int ch = getchar();
	if (ch == 'Y')
	{
		printf("确认成功\n");
	}
	else
	{
		printf("确认失败\n");
	}
	return 0;
}
  • 我们先随便输入一个密码

scanf老是出错?带你详细解决输入缓冲区问题

我们发现,它并没有等我们确认密码就确认失败了。那这个代码哪里出了问题呢?

scanf老是出错?带你详细解决输入缓冲区问题
我们来一步一步分析

  • 开始输入缓冲区是空的,我们输入一串密码到输入缓冲区,并按下回车。scanf 会将 \n 之前的字符都读取走。当 getchar 要读取字符的时候,由于输入缓冲区不为空,所以 getchar 就把 \n 给读取走了。所以直接就进行了判断,而 \n 又不等于 Y ,所以就确认失败了。

所以我们想正确的进行这个代码,是不是要在 scanf 输入之后将输入缓冲区清理掉

  • 怎么清理掉缓冲区呢?我们在 scanf 后面单独加一个 getchar 是不是就可以把 \n 读走呢?

scanf老是出错?带你详细解决输入缓冲区问题

我们发现确实可以了。当我们到这里的时候,可能有的同学就觉得他学会了,实际上还差一点,我们再测试一下:

scanf老是出错?带你详细解决输入缓冲区问题

我们发现又确认失败了,原因很简单,这一次缓冲区里面放的不仅仅是 \n 了。

scanf老是出错?带你详细解决输入缓冲区问题

  • scanf 读取的时候默认的特点是读取到空格结束,scanf 把里面的123456读走了,第一个 getchar 把空格清理走了,但是缓冲区后面还放着 abc\n 呢,下一个 getchar 把 a 读走了,所以也确认失败
  • 我们发现一个 getchar 处理不完缓冲区的所有东西,所以我们可以写一个循环来清理缓冲区。当 getchar 读到的字符不等于 \n 我们就让它继续读。直到读取到 \n 我们就让它停止,这时缓冲区也就清理完毕了。
int main()
{
	printf("请输入密码:>");
	char password[20] = { 0 };
	scanf("%s", password);
	//清理缓冲区
	while (getchar() != '\n')
	{
		;
	}
	printf("请确认密码(Y/N):>");
	int ch = getchar();
	if (ch == 'Y')
	{
		printf("确认成功\n");
	}
	else
	{
		printf("确认失败\n");
	}
	return 0;
}

scanf老是出错?带你详细解决输入缓冲区问题

注:也可以用 gets 和 scanf(“%[ ^ \n]”,str) 读取带空格的字符串,但是我们还是要弄懂缓冲区的原理。

结尾

所以当以后大家做这种输入输出的时候很奇怪,怎么这个地方出问题了,怎么我还没有输入就停止了,这个时候我们就要学会去分析,是不是缓冲区出了问题。文章来源地址https://www.toymoban.com/news/detail-454999.html

到了这里,关于scanf老是出错?带你详细解决输入缓冲区问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++文件操作基础 读写文本、二进制文件 输入输出流 文件位置指针以及随机存取 文件缓冲区以及流状态

    文本文件一般以行的形式组织数据。 包含头文件: #include fstream 类: ofstream(output file stream) ofstream 打开文件的模式(方式):类内open()成员函数参数2.参数1是文件存储/创建路径 例如:fout.open(filename,ios::app); 对于 ofstream,不管用哪种模式打开文件,如果文件不存在,都会创

    2024年01月25日
    浏览(51)
  • libcurl Socks5 堆缓冲区溢出漏洞(CVE-2023-38545)详细分析

    curl 是用于在各种网络协议之间传输数据的命令行工具,libcurl 用于提供处理网络通信和数据传输的 Api 接口。curl 默认下载缓冲区为 102400 字节,但如果设置低于每秒 102400 字节,缓冲区大小会自动设置为更小的值。libcurl 下载缓冲区默认为 16KB,应用程序可通过 CURLOPT_BUFFERSI

    2024年02月08日
    浏览(36)
  • Redis缓冲区溢出及解决方案

    缓冲区(buffer),是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。 在Redis中,主要有三个场景用到了缓冲区的概念。 在客户端和服务器端之间进行通信时,用来暂存客户端发送

    2023年04月12日
    浏览(40)
  • 网络安全威胁,如何解决缓冲区溢出攻击

    目录 一、什么是网络安全 二、什么是缓冲区 三、缓冲区溢出 四、缓冲区溢出攻击的类型 网络安全(Network Security)指的是保护计算机网络及其相关设备、系统和数据免受未经授权访问、破坏、篡改、窃取或滥用的威胁和攻击。随着网络的普及和应用的广泛,网络安全变得越

    2024年02月21日
    浏览(40)
  • [Linux]理解文件系统!动静态库详细制作使用!(缓冲区、inode、软硬链接、动静态库)

            hello,大家好,这里是bang___bang_,今天来谈谈的文件系统知识,包含有缓冲区、inode、软硬链接、动静态库。本篇旨在分享记录知识,如有需要,希望能有所帮助。 目录 1️⃣缓冲区 🍙缓冲区的意义 🍙常见缓冲区刷新策略 🍙缓冲区位置猜想 🍥现象猜测 🍥现象解

    2024年02月13日
    浏览(48)
  • linux缓冲区(buff/cache)内存占用过高解决办法

    1.查看当前内存剩余 2.发现free剩余很少,buff/cache占用很高 3.安装hcache查看谁在占用 3.发现是journal这个东西,这是linux系统日志,出现这种情况,一般是日志没有配置好 查看配置文件 将Storage=persistent 重启日志服务 手动清理缓存区 再次free -m 查看

    2024年01月18日
    浏览(46)
  • 【Linux】理解缓冲区

    我们发现 printf 和 fwrite (库函数)都输出了2次,而 write 只输出了一次(系统调用)。为什么呢?肯定和fork有关! C接口的函数被打印了两次系统接口前后只是打印了一次:和fork函数有关,fork会创建子进程。在创建子进程的时候,数据会被处理成两份,父子进程发生写时拷

    2024年01月23日
    浏览(52)
  • Redis 缓冲区

    缓冲区的应用场景 : 客户端与服务器端的通信时,暂存客户端发送的命令数据,或暂存服务器端返给客户端的数据结果 主从节点间进行数据同步时,暂存主节点接收的写命令和数据 缓冲区 : 避免客户端和服务器端的请求发送和处理速度不匹配 服务器给每个连接的客户端都准

    2024年02月07日
    浏览(69)
  • 8.缓冲区管理

    双缓冲区:TC+M 假设初始状态缓冲区1满,缓冲区2空,工作区为空。 刚开始缓冲区2为空,所以设备可以向缓冲区2中冲入数据耗时T,另一方面刚开始缓冲区1中是满的,所以刚开始就可以把缓冲区1中的数据传送到工作区中,M时刻工作区被充满,CPU就开始处理数据耗时C,处理完

    2024年02月11日
    浏览(41)
  • 理解缓冲区

    对于这样的代码,首先可以肯定的是 printf 语句先于 sleep 执行,既然如此那么就应该是先打印语句然后进行休眠,下面看看结果: 但这里却是先休眠以后再打印语句,这是因为存在一个叫缓冲区的东西,当我们要向外设写入数据(让显示器显示就是向显示器写入数据)时会将

    2023年04月25日
    浏览(72)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包