首页 技巧教程

今天学到scanf的时候,对scanf的内容依然感到迷茫,查找一些文档,才对这部分知识有了稍微清晰的了解。

程序获取输入时的过程比我们想象的复杂 我们考虑一个简单粗暴完整的程序:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int n;
    scanf("%d",&n);
    printf("%d",n);
    return 0;
}

程序运行到 scanf() 时会停止,请求用户输入

假如我输入了365,然后回车

实际上,我从键盘上输入的字符时 3 6 5 ,还有一个换行符'n',(因为我键入了回车)

回车键比较特殊,它先将'n'添加到缓冲区,然后清除缓冲区,将其中所有的字符发送到一个叫做输入列表的地方。

scanf函数以及其他标准输入函数便会立刻从输入列表中获取内容

上述程序按照 %d 的规则从输入列表中获取字符,它获取了'3''6''5' 并且将其转变为整数365 存入了变量n中

此时,你要求 scanf 获取一个整数到n中,它完成了,但是这并不意味着结束,因为输入列表并不干净,按下回车所产生的'n'依然停留在输入列表中。

看下面一段程序:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    int n;
    char c;
    scanf("%d",&n);
    printf("%d",n);
    scanf("%c",&c);  //此时不会停止等待
    printf("%c",c);
    return 0;
}

我们仍然键入365并且回车,此时我们输入的是 3 6 5 和 'n' ,那么此时第二个scanf不会给你输入的机会,因为缓冲区剩余的'n'已经满足变量 c 的需要。

继续看下面的程序:

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

我们继续键入3 6 5 然后回车,

结果是:

c1 = 3

n = 65

c2 =

(即c2 = ‘n’)

格式说明符对于scanf是十分重要的 它便是“规则” 告诉scanf如何从输入列表中获取字符 并且如何做转换

时刻记住输入列表中的内容全是字符 规律就会十分容易

还有需要注意的是 尽管输入列表中的内容都是字符 但是字符还有分类 比如空白符 数字字符 字母字符等

%d 忽略前置空白符 获取连续数字字符 直到遇上非数字字符或者输入列表尾为止

%c 直接获取一个字符到目标变量 “看见什么吃什么”

由于所有输入函数都共享同一个输入列表 所以在整数和字符的混合输入中可能出错

如果你不清楚在获取一个整数以后的下一个获取是否为字符 加上下面的语句是最保险的

while((c = getchar()) != '\n'&&c != EOF);

不停的使用 getchar() 函数获取缓冲区字符,直到获取的字符是换行符'n'或文件结尾EOF为止,这个方法可以完美清除输入缓冲区,并且具备可移植性。

此条语句用来清除输入列表。

总结一下:

  • 在执行scanf函数的时候,会让用户输入1个数据。
  • 数据输入完毕之后,并不是将这个数据直接赋值给变量,而是先将数据存储在缓冲区 输入的任何数据都会存储在缓冲区中。
  • 在执行scanf函数的时候.会先检查缓冲区中是否有数据,

    • 如果缓冲区中没有数据.那么就会让用户从键盘输入;
    • 如果缓冲区中有数据,直接从缓冲区中将数据拿出来,不会让用户输入数据。
  • 当从缓冲区中拿数据的时候

    • 如果要拿的数据的类型是整型或者实型:

      • 如果拿到的是空格 回车 Tab键,就会被自动忽略,继续往下拿。
    • 如果要拿的数据的类型是字符型,不会忽略任何数据。
  • 所以,当我们数字和字符混合输入的时候.字符的接收就有可能会出问题。
  • 解决方案: 在输入字符之前,将缓冲区中的数据全部清空。



文章评论