c语言笔记——对scanf()等输入函数的深入理解

输入函数是我们可以说是接触最早的一批函数了,但是如果不注意的话还是会遇到很多问题,所有我把平时遇到的一些问题和想法写下来。肯定会有不对的地方欢迎大家指正。

##scanf()

  • scanf()这个函数是从输入缓冲区中读取数据的而不是从键盘上读取数据的

这些在上完学校的课之后应该都知道了,可是还是有很多的细节要注意。(原来我也知道可是在使用时还是犯错了。

  • scanf()这个函数在输入时遇到,空格,制表符,回车,和非法输入时结束

注意是输入结束而不是函数结束。

  • scanf()在所有数据域中均有数据且遇到回车时结束。
    -scanf()只有在是%c这个格式时才会读取空格和回车中的换行符

看到有的人在博客中写到scanf()在读取字符串时,会丢弃后面的换行符,然而在试验中发现依然会出现‘跳过’的现象,所已觉得这个解释更合理。

其他还有一些使用方法书上已经十分详细的讲解了,就不多赘述了。
下面通过一些实例说明上面的一些问题:
1.

1
2
3
4
5
6
7
8
9
10
11

#include<stdio.h>
int main()
{
int a, b;
scanf("%d", &a);
scanf("%d", &b);
printf("%d %d", a, b);
}


这个代码在输入的时候除了,一个一个的输入之外,如果你一次输入2 3并按下回车,你会发现第二个scanf()函数被‘跳过’了,直接显示出2 3的结果了。这说明scanf()是从缓冲区直接读取数据,而不是键盘,只有当输入缓冲区没有数据才会要求从键盘输入。
2.

1
2
3
4
5
6
7
8
9
#include<stdio.h>
int main()
{
char a[10];
scanf("%s", a);
printf("%s", a);
}


这样一段代码如果你输入‘hello world’你会发现输出的只有hello,这是因为它在读取到空格的时候就停了,所已一般不用它来输入字符串,虽然也可以通过scanf("%[^\n]",a)来实现输入句子,但是还是用gets更好一点。(这是一个正则表达式的用法,意思是遇到\n才停下来,其实对于这个我也不是很清楚)
3.

1
2
3
4
5
6
7
8
9
10

#include<stdio.h>
int main()
{
char a, b;
scanf("%c", &a);
scanf("%c", &b);
printf("%d %d", a, b);
}

这段代码的本意很简单就是输出输入的两个的字符在ASCII表中的值,但是实际结果是如果你会车后输入b,会发现b的值一直是10,或像上面一样用空格隔开输入,那么b就一直是32.这是因为当为%c时scanf()可以读入空格和回车符。当输入完a的值之后,scanf()读走了一个值,而回车还留在输入缓冲区了,第二个就直接读取了,查表发现回车就对应10,空格就对应32,制表符当然也不例外了。如果是读取字符串就不会出现这个问题了。

对了还有一个就是在使用scanf_s()这个函数的时候因为安全原因,在输入字符串的时候如果不写缓冲区大小(也就是最大字符长度)运行的时候就会报错,在变量后面加个长度就可以了。


从临近考试周到寒假都快过了大半了,在这段时间里一直在玩耍实在是罪过啊。现在找时间把自己未完成的博文写完,不知道自己还记得不。


##getch()和getche()
  这两个函数的功能非常的相似,都是直接从键盘读取数据而不是从缓冲区,他们的区别是前者无回显后者有回显。在这里回显的意思就是回在屏幕上显示出你输入的东西,下面举个简单的例子就很容易明白了。

1
2
3
4
5
6
7
8
#include<stdio.h>
#include<conio.h>
int main()
{
char a;
a=getch();
printf_s("%c", a);
}

这个程序如果你输入的是‘a’那么显示的只有a,而如果把getch()换成getche()那么结果就是‘aa’了。这说明getch()这个函数没有回显也就是不把输入的内容显示在显示器上。

##gets()
  这个函数的功能是从输入缓冲区中读取字符串,直到遇到换行或者是EOF才停止。这个函数一般用来输入句子。但是和scnf()用来输入字符串一样存在安全问题。这个函数的原型是:

1
char *gets( char *buffer );

这个函数的形参只有一个指针,没有限制输入的数目,也就是说这个函数可以无限的输入这样很有可能就会造成溢出。所以现在用gets_s()来代替这个函数。

##清空输入缓冲区
  有的时候我们需要清空输入缓冲区,然后重新输入数据。常用的有fflush(stdin);这个函数。某些编译器(如VC6)支持用 fflush(stdin) 来清空输入缓冲,但是并非所有 编译器都要支持这个功能(linux 下的 gcc 就不支持),因为标准中根本没有定 义 fflush(stdin)。
  而更加实用也更加经典的则是:

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

由代码知,不停地使用getchar()获取缓冲区中字符,直到 获取的字符c是换行符’\n’或者是文件结尾符EOF为止。这个方法可以完美清除输入缓冲区,并且具备可移植性。

以上是我对于c语言的一些理解,如有不对的地方欢迎大家评论指正,也欢迎大家交流学习。