关于【C语言】中scanf与getchar的用法和常见错误详解 2

简介: 关于【C语言】中scanf与getchar的用法和常见错误详解

三.几种常见错误详解

1.不理解原理导致的错误

下面以getchar为例具体讲解一下这种错误的产生及解决方法

代码如下:

#include<stdio.h>
int main()
{
  char password[20] = {0};
  printf("请输入密码:");
  scanf("%s", password);//以字符串的形式输入
  printf("请确认密码(Y/N):>");//用户输入Y/N确认
  int ch = getchar();
  if (ch == 'Y')
  {
    printf("确认成功\n");
  }
  else
  {
    printf("确认失败\n");
  }
  return 0;
}

来看看这段代码运行的结果

32f0dae61d8643b4852522b0a0684704.png

嗯?什么情况,我还没输入Y或N怎么就确认失败了??

68b9c91bc0714e48b4de629ce51a2c3e.jpg


好了,这里我就不卖关子了。

3f082b11a9a64f389bb03133e60fdfce.png

scanf和getchar这两个输入函数,它们都是从键盘上得到我们的数据,而不是直接从键盘上来读取我们的数据。它们和键盘之间有一个区域叫输入缓冲区。所有输入的数据都会先放在输入缓冲区中。

在存放输入的数据时,输入函数先来看看输入缓冲区中是否有数据,如果有,它就直接拿走并储存,而不需要从键盘再输入数据,如果输入缓冲区中什么都没有,则需要从键盘输入,再拿走。

带入上面的代码试试

864ffed5451540109dcfe1c831d439a5.png

当我们输入123456时,为了把“123456”放进去,其实还敲了一个回车,因此实际上输入缓冲区中存放的是“123456\n”。

86dd6e9716e642b1ae3694b55f4564b1.png


程序继续运行,此时它把“123456”提取出来,输入缓冲区中还留有一个“\n”.

dafeffea35ef448e8dc0d4197123dc56.png


注意:

程序走到这一步后,进行第二次从键盘中读取( int ch = getchar() ),此时输入缓冲区中还滞留有上次未提前出来的“\n”,因此不再从键盘上读取数据,直接把“\n”从输入缓冲区提取出来。此时ch的地址中存放的就是“\n”,显然不等于’Y’,所以输出为“确认失败”

看了上面的讲解,你弄懂了吗?接下来我们来讲讲改进方法


其实改进很简单,它不是在输入缓冲区中还滞留有“\n”吗?我再使用一个输入函数把它给读走不就行啦?

int main()
{
  char password[20] = { 0 };
  printf("请输入密码:");
  scanf("%s", password);
  printf("请确认密码(Y/N):>");
  getchar();//把多余的\n取走
  int ch = getchar();
  if (ch == 'Y')
  {
    printf("确认成功\n");
  }
  else
  {
    printf("确认失败\n");
  }
  return 0;
}

e4e80e8836444812b1bff563ed35aee6.png


这种方法雀氏可行,但是如果这样呢?

请输入密码:12345 6(中间加空格)


591c437c5924462eb55f778a8d694ebf.png


?怎么又这样了??我不是把“\n”读走了吗?

解释亿下:

f4579d7d4f2441ed8034a57c8772df86.png

此时输入缓冲区中是这样的。

6fd6ffd6de014245af5cff0cd3e609ce.png


轮到scanf来取缓冲区中的数据,当它读到空格的时候,它就不再继续往下读了(这是scanf的一个作用性质)。

所以scanf就只取走了12345,而缓冲区中还剩下(空格)6\n。

97a894350e5747a2ac339e46834a2ddc.png

此时,getchar()读取一个字符,它把空格给读走了,输入缓冲区中剩下6\n.

a156de7fcd6d4394b05b78aa76178518.png

最后,int ch = getchar()把6给读走,不等于’Y’,于是打印“确认失败”

78623cffe61e4f6d845b5284f7fe339d.jpg

难道没有什么办法避免这种错误吗?

什么话,没有办法我会把这种错误写出来吗??这不是自己打自己脸吗?

解决方案

介于输入缓冲区中一直存放有数据未被清理,我们需要把缓冲区中多余的数据先全部清走。

方式:

采用一个循环,只要没读到\n,我们就一直用getchar读。

代码实现如下:

#include<stdio.h>
int main()
{
  char password[20] = {0};
  printf("请输入密码:");
  scanf("%s", password);
  while ( getchar() != '\n');//把缓冲区中多余的内容全读走,直到\n停止
  printf("请确认密码(Y/N):>");
  int ch = getchar();
  if (ch == 'Y')
  {
    printf("确认成功\n");
  }
  else
  {
    printf("确认失败\n");
  }
  return 0;
}

结果:

f160ea604dfe4b1a9f82722dabeae13b.png

完美解决


f2bac6e1989641b3bbce56935eb9a759.gif

2.输入参数不符合输入控制符要求

比如以下代码:

# include <stdio.h>
int main(void)
{
    char m;
    int n;
    scanf("%c%d", &m);
    printf("m = %c, n = %d\n", m, n);
    return 0;
}

不做过多解释,scanf中输入控制符要求你输入两个数据,结果你的输入参数只输入了一个,你觉得这可能正确吗?

但其实对于多组输入来说,不输入正确个数的数据也有一定意义,详情可以看看我的这篇博客:关于C语言中scanf多组输入的实现

需要注意的是:

一但发生这种错误时,编译器可能并不会报错,但是从程序上来说它是绝对错误的,当发现异常时,一定要多多注意认真检查一下输入函数。

总结

以上就是今天要讲的所有内容啦

有任何疑问欢迎在评论区或者私信博主指出哦。

大噶(家)下次见啦!

如果感觉有帮助的话不妨三连一下这个新人博主。你们的支持就是我更新的动力。

(可莉请求你们三连支持一下博主!!!点击下方评论点赞收藏帮帮可莉吧)

20fa3306e76244de9879742c165c792a.gif

参考博客


目录
相关文章
|
2月前
|
C语言
C语言判断逻辑的高阶用法
在C语言中,高级的判断逻辑技巧能显著提升代码的可读性、灵活性和效率。本文介绍了六种常见方法:1) 函数指针,如回调机制;2) 逻辑运算符组合,实现复杂条件判断;3) 宏定义简化逻辑;4) 结构体与联合体组织复杂数据;5) 递归与分治法处理树形结构;6) 状态机管理状态转换。通过这些方法,可以更高效地管理和实现复杂的逻辑判断,使代码更加清晰易懂。
229 88
|
1月前
|
C语言
初识C语言:与计算机的交流之输入与输出(scanf和printf)
初识C语言:与计算机的交流之输入与输出(scanf和printf)
170 0
|
2月前
|
C语言
【C语言基础考研向】05 scanf读取标准输入超详解
本文详细解析了C语言中`scanf`函数的工作原理及常见问题。首先介绍了`scanf`如何处理标准输入,并通过示例说明了为何有时会出现阻塞现象及其解决办法。接着探讨了当输入包含多种数据类型时,特别是字符型数据的处理方式,强调了格式控制的重要性,并给出了正确的输入格式示例。通过正确配置,可以避免因空格和换行符导致的问题,确保数据准确读取。
74 10
|
2月前
|
存储 C语言
【C语言基础考研向】10 字符数组初始化及传递和scanf 读取字符串
本文介绍了C语言中字符数组的初始化方法及其在函数间传递的注意事项。字符数组初始化有两种方式:逐个字符赋值或整体初始化字符串。实际工作中常用后者,如`char c[10]=&quot;hello&quot;`。示例代码展示了如何初始化及传递字符数组,并解释了为何未正确添加结束符`\0`会导致乱码。此外,还讨论了`scanf`函数读取字符串时忽略空格和回车的特点。
|
2月前
|
C语言
C语言程序设计核心详解 第三章:顺序结构,printf(),scanf()详解
本章介绍顺序结构的基本框架及C语言的标准输入输出。程序从`main()`开始依次执行,框架包括输入、计算和输出三部分。重点讲解了`printf()`与`scanf()`函数:`printf()`用于格式化输出,支持多种占位符;`scanf()`用于格式化输入,需注意普通字符与占位符的区别。此外还介绍了`putchar()`和`getchar()`函数,分别用于输出和接收单个字符。
|
3月前
|
存储 缓存 编译器
【C语言篇】scanf和printf万字超详细介绍(基本加拓展用法)(下篇)
scanf处理⽤⼾输⼊的原理是,⽤⼾的输⼊先放⼊缓存,等到按下回⻋键后,按照占位符对缓存进⾏解读。 解读⽤⼾输⼊时,会从上⼀次解读遗留的第⼀个字符开始,直到读完缓存,或者遇到第⼀个不符合条件的字符为⽌。
162 2
|
3月前
|
存储 C语言
【C语言篇】scanf和printf万字超详细介绍(基本加拓展用法)(上篇)
printf 的作⽤是将参数⽂本输出到屏幕。它名字⾥⾯的 f 代表 format (格式化),表⽰可以定制输出⽂本的格式。
75 1
|
1月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
34 3
|
7天前
|
C语言
c语言调用的函数的声明
被调用的函数的声明: 一个函数调用另一个函数需具备的条件: 首先被调用的函数必须是已经存在的函数,即头文件中存在或已经定义过; 如果使用库函数,一般应该在本文件开头用#include命令将调用有关库函数时在所需要用到的信息“包含”到本文件中。.h文件是头文件所用的后缀。 如果使用用户自己定义的函数,而且该函数与使用它的函数在同一个文件中,一般还应该在主调函数中对被调用的函数做声明。 如果被调用的函数定义出现在主调函数之前可以不必声明。 如果已在所有函数定义之前,在函数的外部已做了函数声明,则在各个主调函数中不必多所调用的函数在做声明
22 6
|
27天前
|
存储 缓存 C语言
【c语言】简单的算术操作符、输入输出函数
本文介绍了C语言中的算术操作符、赋值操作符、单目操作符以及输入输出函数 `printf` 和 `scanf` 的基本用法。算术操作符包括加、减、乘、除和求余,其中除法和求余运算有特殊规则。赋值操作符用于给变量赋值,并支持复合赋值。单目操作符包括自增自减、正负号和强制类型转换。输入输出函数 `printf` 和 `scanf` 用于格式化输入和输出,支持多种占位符和格式控制。通过示例代码详细解释了这些操作符和函数的使用方法。
34 10