众所周知,C语言中的scanf函数的作用是从标准输入设备(通常是键盘)读取输入值,并存储到参数列表中指针所指向的内存单元。
下面从几个方面说一下一些稍微细节的东西。下面的实验都在vc6.0中通过。
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。
scanf以删除的方式从缓冲区读入数据(来自标准输入设备的数据存储在缓冲区),也就是说,scanf从缓冲区读入一个数据项,该数据项在缓冲区中就被清除掉了。
而如果scanf需要读取一个数据项,返现缓冲区当前是空的,那么程序就会在scanf代码处阻塞,等待用户输入,scanf函数接收到相应的数据项之后,在缓冲区中将这一数据项清除,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);
运行效果也和上面的相同。
#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函数与空格回车的用法说明就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持小牛知识库。
在我的C程序中,我使用了一个带有以下参数的void函数:一个2D int数组、一个用于创建新动态数组的int指针和一个最后的int指针,该指针将保存函数内部发生的计数。因此,动态数组是使用malloc在函数中创建的,一切正常,直到调用函数后在main()中打印其元素。我得到的是垃圾,而不是我应该看到的数字。以下是功能代码:
本文向大家介绍浅析C语言中strtol()函数与strtoul()函数的用法,包括了浅析C语言中strtol()函数与strtoul()函数的用法的使用技巧和注意事项,需要的朋友参考一下 C语言strtol()函数:将字符串转换成long(长整型数) 头文件: strtol() 函数用来将字符串转换为长整型数(long),其原型为: 【参数说明】str 为要转换的字符串,endstr 为第一个不能
我试图理解scanf和输入缓冲区之间的关系。我将scanf与以下格式字符串一起使用: 并尝试理解为什么我可以输入尽可能多的空白(输入,空白,选项卡)后,我输入一个数字,如54,并按回车键。 据我所知,我按下的每一个键都会被放入输入缓冲区,直到我按下回车键。 因此,如果我输入54并按Enter键,输入缓冲区包含3个元素,两个数字和换行符。所以我的缓冲区看起来像[5][4][\n] 现在从左到右计算s
函数的返回值是指函数被调用之后,执行函数体中的代码所得到的结果,这个结果通过 return 语句返回。 return 语句的一般形式为: 或者: 有没有 都是正确的,为了简明,一般也不写 。例如: 对C语言返回值的说明: 1) 没有返回值的函数为空类型,用 表示。例如: 一旦函数的返回值类型被定义为 void,就不能再接收它的值了。例如,下面的语句是错误的: 为了使程序有良好的可读性并减少出错,
我试图写一个程序与选择菜单使用开关语句在C.这是我的代码: 该程序将重复执行,直到从键盘输入“q”字符。问题是,每当我第一次尝试从键盘输入“1”(执行案例1),下一次输入“1”或“2”时,程序将跳过案例1(或2)并直接进入下一个循环,但在下一个循环后,它会正常执行案例1(或2)。此外,案例2(没有scanf()函数)的每一项都能正常工作。我还尝试从案例1中删除scanf,之后案例1正常执行。以下是
在 Go 语言开篇中我们已经知道,Go 语言与 C 语言之间有着千丝万缕的关系,甚至被称之为 21 世纪的C语言。 所以在 Go 与 C 语言互操作方面,Go 更是提供了强大的支持。尤其是在 Go 中使用 C,你甚至可以直接在 Go 源文件中编写 C 代码,这是其他语言所无法望其项背的。 格式: 在 import "C" 之前通过单行注释或者通过多行注释编写C语言代码 在 import "C" 之