C语言中scanf函数与空格回车的用法说明

众所周知,C语言中的scanf函数的作用是从标准输入设备(通常是键盘)读取输入值,并存储到参数列表中指针所指向的内存单元。

下面从几个方面说一下一些稍微细节的东西。下面的实验都在vc6.0中通过。

1、scanf的返回值

scanf通常返回的是成功赋值(从标准输入设备赋值到参数列表所指定的内存区域)的数据项数,如果出错或是遇到end of file(注意,如果想从键盘输入EOF,在windows的DOS窗口用Ctrl+Z 或F6;在UNIX系统上,用CTRL+D。),则返回EOF,比如:

scanf("%d%d", &x, &y);

如果x和y都被成功读入,那么scanf的返回值就是2;

如果只有x被成功读入,返回值为1;

如果x和y都未被成功读入,返回值为0;

如果遇到错误或遇到end of file,返回值为EOF。

2、scanf的处理机制

scanf以删除的方式从缓冲区读入数据(来自标准输入设备的数据存储在缓冲区),也就是说,scanf从缓冲区读入一个数据项,该数据项在缓冲区中就被清除掉了。

而如果scanf需要读取一个数据项,返现缓冲区当前是空的,那么程序就会在scanf代码处阻塞,等待用户输入,scanf函数接收到相应的数据项之后,在缓冲区中将这一数据项清除,scanf函数返回,程序继续执行。

3、scanf对不同类型输入的处理方式

首先,要清除一个概念:空白字符(white space)。一般,程序中所指的空白字符是指空格(space),回车(enter)和指标符(table)。

3.1 整数%d

对于整型数据的输入,也就是说"%d"类型的输入,scanf默认的分割符是所有的空白字符(空格,回车和指标符都行)。

也就是说如果一个scanf函数中出现scanf("%d%d",&a,&b),那么用任何一个空白字符来分隔两个整数a,b的值,变量a,b都可以接收到正确的输入。

另外,要注意的是,scanf对于数字输入,会忽略输入数据项前面的空白字符。下面是例1:

Code:
#include<stdio.h>
int main()
{
 int a,b;
 printf("Input the value of a and b:");
 while(scanf("%d%d",&a,&b)!=EOF)
 {
 printf("a=%d,b=%d\n",a,b);
 printf("Input the value of a and b:");
 }
 return 0;
}
Output:
Input the value of a and b:123 456
a=123,b=456
Input the value of a and b:123 456
a=123,b=456
Input the value of a and b:123
456
a=123,b=456
Input the value of a and b:
123 456
a=123,b=456
Input the value of a and b:  123 456
a=123,b=456
Input the value of a and b: 123 456
a=123,b=456
Input the value of a and b:^Z
Press any key to continue

3.2 字符串%s

scanf对于字符串输入的处理和对整数类似,会忽略前导的空白字符,而且默认的分隔符是所有的空白字符。但是,要注意的是,由于C语言中,没有string类型,都是用char型数组来表示。

因此,scanf会为每一个输入的字符串最后加一个‘\0'。下面是一个例子,可以看出scanf这货的边界控制还是要小心。

如下例2。

#include<stdio.h>
int main()
{
 char a[5],b[5];
 int i;
 printf("Input the value of a and b:");
 while(scanf("%s%s",a,b)!=EOF)
 {
 printf("a=%s,b=%s\n",a,b);
 for(i=0;i<5;i++)
 printf("%d:(%c) ",a[i],a[i]);
 printf("\n");
 for(i=0;i<5;i++)
 printf("%d:(%c) ",b[i],b[i]);
 printf("\n");
 printf("Input the value of a and b:");
 }
 return 0;
}

运行结果:

3.3 字符%c

scanf在处理对字符数据的输入时,既不会忽略前导空白字符,默认也没有任何分隔字符。所有的字符,包括空白字符都会被当成输入字符。

下面是例3。

#include<stdio.h>
int main()
{
 char a ,b ;
 printf("Input the value of a and b:");
 while(scanf("%c%c",&a,&b)!=EOF)
 {
 printf("a=%c,b=%c\n",a,b);
 printf("Input the value of a and b:");
 }
 return 0;
}

运行结果:

可以看出,在对字符数据输入的时候,由于缓冲区中有回车空格等数据,会导致输入数据比较诡异,为了解决这个问题,有以下方法:

(1) 清空缓冲区

在微软系统中,有一个名为fflush(stdin)的函数,可以用来清空缓冲区,

如下例4。

#include<stdio.h>
int main()
{
 char a ,b ;
 printf("Input the value of a and b:");
 while(scanf("%c%c",&a,&b)!=EOF)
 {
 printf("a=%c,b=%c\n",a,b);
 fflush(stdin);
 printf("Input the value of a and b:");
 }
 return 0;
}

运行结果:

(2)将缓冲区的数据读出来

有的编译系统并没有定义stdin的fflush操作,这个时候,可以把缓冲区中的数据读出来,有如下几种可行的方法:

1) getchar()

将例4中的fflush(stdin);语句换成

char c;

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

运行效果和上面的相同。

2) gets()

char* gets(char* buffer)从stdin流中读取字符串,直至接受到换行符或EOF时停止,并将读取的结果存放在buffer指针所指向的字符数组中。换行符不作为读取串的内容,读取的换行符被转换为null值,并由此来结束字符串。

读入成功,返回与参数buffer相同的指针;读入过程中遇到EOF(End-of-File)或发生错误,返回NULL指针。

所以在遇到返回值为NULL的情况,要用ferror或feof函数检查是发生错误还是遇到EOF。

要注意的是gets函数可以无限读取,不会判断上限,所以应该确保buffer的空间足够大,以便在执行读操作时不发生溢出。如果溢出,多出来的字符将被写入到堆栈中,这就覆盖了堆栈原先的内容,破坏一个或多个不相关变量的值。

将例4中的fflush(stdin);语句换成

char c[10];

gets(c);

运行效果也和上面的相同。

4、在stackoverflow上看到的一个问题

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char *method1(void)
{
 static char a[4];
 scanf ("%s\n", a);
 return a;
}

int main(void)
{
 char *h = method1();
 printf ("%s\n", h);
 return 0;
}

运行结果:

ab
cd
ab
Press any key to continue

可以发现,输如两次之后才会输出。这个现象比较诡异,原因如下:

White space (such as blanks, tabs, or newlines) in the format string match any amount of white space, including none, in the input. Everything else matches only itself.

Thus with scanf ("%s\n", a) it will scan for a string followed by optional white space. Since after the first newline more whitespace may follow, scanf is not done after the first newline and looks what's next. You will notice that you can enter any number of newlines (or tabs or spaces) and scanf will still wait for more.

However, when you enter the second string, the sequence of whitespace is delimited and scanning stops.

以上这篇C语言中scanf函数与空格回车的用法说明就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • C语言清除scanf()缓存的案例讲解

    又重新过一遍C语言,感觉每次重学C语言都有不同的感受,遇到了一个问题,就是scanf()这个问题,其实细究起来,也有很多可以值得深挖的,实际上每次细细的挖掘的话,都是对C语言的更透彻的认识. 那么下面我就对scanf()中清除输入缓冲区的方法讲解: 应用场景:我们使用多个scanf()的时候,如果输入缓冲区还有数据的话,那么scanf()就不会询问用户输入,而是直接就将输入缓冲区的内容拿出来用了,这就导致了前面的错误影响到后面的内容,为了隔离这种问题, 总的思想:通过各种方法将输入缓冲区的内容读

  • c语言 sscanf,scanf,fscanf正则表达式用法

    每种语言都对正则表达式有着不同程度的支持,在C语言中,有输入功能的这三个函数对正则表达式的支持并不强大,但是我们还是有必要了解一下. 首先来看看他们的原型: #include <stdio.h> int scanf(const char *format, ...); int fscanf(FILE *stream, const char *format, ...); int sscanf(const char *str, const char *format, ...); 均可以接受变参,ss

  • C语言 scanf输入多个数字只能以逗号分隔的操作

    C之scanf输入多个数字只能以逗号分隔,而不能用空格 TAB空白符分隔 #include <stdio.h> int main() { int num_max(int x,int y,int z); int a,b,c,max; scanf("%d,%d,%d",&a,&b,&c); max=num_max(a,b,c); printf("max=%d",max); return 0; } int num_max(int x,i

  • 解决C语言中使用scanf连续输入两个字符类型的问题

    昨天用C编程,遇到一个关于scanf的细节问题,假如运行如下程序: #include<stdio.h> int main() { char ch1,ch2; printf("Input for ch1:/n"); scanf("%c",&ch1); printf("ch1=%c/n",ch1); printf("Input for ch2:/n"); scanf("%c",&ch

  • c语言获取用户输入字符串是scanf和gets的区别详解

    解释 gets(s)函数与 scanf("%s",&s) 相似,但不完全相同,使用scanf("%s",&s) 函数输入字符串时存在一个问题,就是如果输入了空格会认为字符串结束,空格后的字符将作为下一个输入项处理,但gets()函数将接收输入的整个字符串直到遇到换行为止. 1.scanf() 所在头文件:stdio.h 语法:scanf("格式控制字符串",变量地址列表); 接受字符串时:scanf("%s",

  • C语言中scanf函数与空格回车的用法说明

    众所周知,C语言中的scanf函数的作用是从标准输入设备(通常是键盘)读取输入值,并存储到参数列表中指针所指向的内存单元. 下面从几个方面说一下一些稍微细节的东西.下面的实验都在vc6.0中通过. 1.scanf的返回值 scanf通常返回的是成功赋值(从标准输入设备赋值到参数列表所指定的内存区域)的数据项数,如果出错或是遇到end of file(注意,如果想从键盘输入EOF,在windows的DOS窗口用Ctrl+Z 或F6:在UNIX系统上,用CTRL+D.),则返回EOF,比如: sca

  • C语言中scanf函数的原样输入的坑及解决

    目录 scanf函数的原样输入的坑及解决 1.scanf函数格式控制后面输入 2.scanf函数的输入是有顺序的 3.最重要的一点就是scanf切记要原样输入 4.还有一个 scanf输入多个数据出现的问题 问题引出 执行原理 程序分析 解决方案 scanf函数的原样输入的坑及解决 scanf函数是C语言里一个输入函数,但其有很多地方需要注意: 1.scanf函数格式控制后面输入 的应该是变量的地址而不是变量本身(即变量名) 例,输入a,b 两个整型变量的值的时候,很多初学者会写成 scanf(

  • 详解C语言中scanf函数使用的一些注意点

     (一)基本介绍 Scanf是系统自带的函数,声明包含在stdio.h文件中,因此要是有该函数,必须加载#include<stdio.h>头文件.当执行到scanf函数时,程序就暂停等待用户输入,该函数只接受变量的地址,格式为&变量名.是一个阻塞式的函数,2用户输入完毕后,则将值赋值给变量,至此函数调用完毕.敲回车键告知计算机键入完毕. (二)使用注意 ①. 使用scanf函数输入一个字符变量.Char a; scanf("%c",&a); ②. 同时输入多

  • C语言中scanf与scanf_s函数的使用详解

    目录 1.scanf_s(是vs提供的函数) 2.scanf(标准的库函数) 3.总结 1.scanf_s(是vs提供的函数) a.代码1 int main() { char a = 0; //scanf_s("%c", &a, 1); scanf_s("%c", &a, sizeof(a)); return 0; } scanf_s有三个参数,最后一个是变量a所占据空间的大小(单位为字节),这里可以写1,也可以写sizeof(a).如果a为整型的话

  • C语言中scanf与scnaf_s函数详解

    目录 scanf_s 使用scanf_s scanf 使用scanf 总结 scanf_s scanf_s()函数是Microsoft公司VS开发工具提供的一个功能相同的安全标准输入函数,从vc++2005开始,VS系统提供了scanf_s().在调用该函数时,可以提供一个数字以表明最多读取多少位字符. MSDN上scanf_s的简单模型:int scanf_s( const char *format [, argument]...);一般我们常用的格式:scanf_s(输入格式,输入流 [,输

  • c语言中scanf的基本用法

    前言 scanf()是C语言的格式输入函数,和printf函数一样被声明在stdio.h头文件中,它的基本使用很简单: 1 int a; 2 scanf("%d",&a);//程序执行到这里时,就等待用户输入:它接收的是变量的地址 //所以一般情况下除了指针型变量和数组名要给变量加上取地址符& 下面主要介绍了C语言中scanf的用法和注意事项,下面来一起看看详细的介绍吧 scanf概念 scanf是格式输入函数,功能是在屏幕上输入指定的信息.简单的来说和printf相似

  • C语言中getch()函数详解及简单实例

    C语言中getch()函数详解及简单实例 前言: 这个函数是一个不回显函数,当用户按下某个字符时,函数自动读取,无需按回车,有的C语言命令行程序会用到此函数做游戏,但是这个函数并非标准函数,要注意移植性! 所以有这样的一个接口,那就很牛逼了,至少可以做个游戏来玩下,结合ASCII码,很容易写个方向键控制的2048或者贪吃蛇等等有趣的游戏出来. 以下是以一个简单的例子: 你会发现当你按下对应的按键的时候就会打印相应的语句. #include <stdio.h> #include <fcnt

  • C语言中atoi函数模拟实现详析

    目录 一.atoi函数是什么? 二.atoi函数模拟实现 总结 一.atoi函数是什么? int atoi ( const char * str ); 功能:将字符串转换为整数. 解析C字符串str,将其内容解释为一个整数,该整数作为int值返回. 该函数首先丢弃尽可能多的空白字符,直到找到第一个非空白字符.然后,从这个字符开始,取一个可选的初始加号或减号,后面跟着尽可能多的数字,并将它们解释为一个数值. 例:" -123456" 转换为 -123456 字符串可以在构成整数的字符之后

  • C语言中pow函数使用方法、注意事项以及常见报错原因

    目录 1.首先使用pow函数必须要加头文件 : 2.pow()用来计算以x 为底的 y 次方值,然后将结果返回. 3.注意可能引起报错的原因 可能导致错误的情况: 总结 1.首先使用pow函数必须要加头文件 : #include<math.h> pow() 函数用来求 x 的 y 次幂(次方),x.y及函数值实际上为double型 ,其在使用中的原型为:double pow(double x, double y); 注意,在某些特定的情况之下,pow函数的double类型可能会引起输出结果的错

  • Go语言中append函数用法分析

    本文实例分析了Go语言中append函数用法.分享给大家供大家参考.具体如下: Go语言中append的功能十分强大,使用它可以使很多功能的实现变得更加简洁.以下为简单对比: .将一个slice插入到另一个slice的指定位置: 不使用append: 复制代码 代码如下: func insertSliceAtIndex(slice_origin []int, slice_to_insert []int,      insertIndex int) (result []int, err error

随机推荐