关于【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语言第四弹---printf和scanf详解
C语言第四弹---printf和scanf详解
|
6天前
|
存储 缓存 编译器
C语言之scanf浅析
C语言之scanf浅析
14 0
|
9天前
|
Unix Linux 编译器
C语言中EOF的用法
C语言中EOF的用法
7 0
|
9天前
|
存储 编译器 C语言
C语言中scanf函数的使用
C语言中scanf函数的使用
12 0
|
21天前
|
存储 C语言
爱上C语言:scanf、gets以及getchar输入字符串你真的懂了吗
爱上C语言:scanf、gets以及getchar输入字符串你真的懂了吗
|
2月前
|
C语言
C语言4🔥:运算符,运算符的基本用法
C语言4🔥:运算符,运算符的基本用法
33 0
|
2月前
|
存储 程序员 C语言
scanf函数:C语言中的标准输入工具
在C语言编程中,scanf函数是一个非常重要的工具,用于从标准输入(通常是键盘)读取数据。这个函数允许程序员按照指定的格式读取和存储各种类型的数据。scanf函数的名称来源于“scan formatted”,意味着它会按照特定的格式扫描输入。
14 0
|
2月前
|
存储 C语言
C语言用scanf函数数据
C语言用scanf函数数据
11 0
|
2月前
|
存储 C语言 索引
C语言用scanf函数输入数据
C语言用scanf函数输入数据
13 0
|
2月前
|
存储 C语言
C语言用scanf函数程序处理
C语言用scanf函数程序处理
10 0