-
2021-05-22 15:59:20
例1
#include
main()
{int i;int b;
scanf("%d",&i);
getchar();
}
为什么只输入一个数字或字母都会退出?
例2
#include
main()
{int i;int b;
scanf("%d",&i);
scanf("%d",&b);
}
为什么输入一个数字不会退出,输入一个字母会退出?
例3
#include
main()
{int i;int b;
scanf("%d",&i);
getch();
}
为什么输入一个数字或者字母都不会退出?
例1
/* 输入数字和字母实际上都是输入两个字符,你输入的数字getchar()读取下面的回车.
如果是字母getchar()读取你输入的字母,你可以试一试.*/
例2
/* 在输入一个数字的时候,第一个scanf函数读取第一个数字,第二个scanf函数等待输入(scanf函数会跳过空格操作符,包括回车,空格等),所以 不能退出。在输入一个字母的时候,第一个不能匹配,并不能把第一个字母从输入流中去掉,所以第二个scanf函数仍然读取到一个字母而失去匹配,从而退出 函数,所以,不管有多少个int类型的scanf函数都会在输入一个字母的情况下退出
例3
/*getch()这个函数是按任意键退出,前面你不管输入多少,到这里也得输入就是这样*/
再来看看百度百科上的解释SCANF
1.scanf函数的一般形式
scanf(格式控制,地址表列)
int scanf(char *format[,argument,...]);
“格式控制”的含义同printf函数;“地址表列”是由若干个地址组成的表列,可以是变量的地址,或字符串首地址。
scanf()函数返回成功赋值的数据项数,出错时则返回EOF。
例题 scanf函数输入数据。
#include
void main(){
int a,b,c;
printf("input a,b,c\n");
scanf("%d%d%d",&a,&b,&c);
printf("a=%d,b=%d,c=%d",a,b,c);
}
格式字符 说明
%a 读入一个浮点值(仅C99有效)
%A 同上
%c 读入一个字符
%d 读入十进制整数
%i 读入十进制,八进制,十六进制整数
%o 读入八进制整数
%x 读入十六进制整数
%X 同上
%c 读入一个字符
%s 读入一个字符串
%f 读入一个浮点数
%F 同上
%e 同上
%E 同上
%g 同上
%G 同上
%p 读入一个指针
%u 读入一个无符号十进制整数
%n 至此已读入值的等价字符数
%[] 扫描字符集合
更多相关内容 -
scanf函数用法
2021-04-02 15:01:55scanf()函数是通用终端格式化输入函数,它从标准输入设备(键盘) 读取输入的信息。可以读入任何固有类型的数据并自动把数值变换成适当的机内格式。 2、调用格式: scanf("<格式化字符串>",<地址表>); ...1、功能:执行格式化输入
scanf()函数是通用终端格式化输入函数,它从标准输入设备(键盘) 读取输入的信息。可以读入任何固有类型的数据并自动把数值变换成适当的机内格式。
使用scanf()函数需要包含头文件 <stdio.h>
2、调用格式:
scanf("<格式化字符串>",<地址表>);
scanf()函数返回成功赋值的数据项数,出错时则返回EOF。
eg.对于"a-b 10:6"的输入格式
int score1[100],score2[100]; char team1[100],team2[100]; int i=0; while(scanf("%c-%c %d:%d",&team1[i],&team2[i],&score1[i],&score2[i])!=EOF) i++; ...
3、scanf()函数的控制串由三类字符组成:
(1)格式化说明符;
(2)空白符;
(3)非空白符;4、格式化说明符
格式字符 说明 %c 读入一个字符 %s 读入一个字符串 %d 读入十进制整数 %f 读入一个浮点数 %u 读入一个无符号十进制整数 %o 读入八进制整数 %p 读入十六进制整数 %x 输出十六进制整数 int main() { int a; scanf("%p",&a); //输入十六进制数 printf("%d",a); //输出十进制数 printf("0x%x",a); //输出十六进制数 } %p是输入一个十六进制的数 %d是输出一个十进制的数 %x是输出一个十六进制的数
附加格式说明字符表
修饰符 说明 L/l 长度修饰符 输入"长"数据 h 长度修饰符 输入"短"数据 W 整型常数 指定输入数据所占宽度 * 星号 空读一个数据 hh,ll同上h,l但仅对C99有效。
5、空白字符
空白字符会使scanf()函数在读操作中略去输入中的一个或多个空白字符,空白符可以是space,tab,newline等等,直到第一个非空白符出现为止。
6、 非空白字符
一个非空白字符会使scanf()函数在读入时剔除掉与这个非空白字符相同的字符。
-
C语言scanf函数用法详细解释!
2018-12-29 20:51:24函数名: scanf 功 能: 执行格式化输入 用 法: int scanf(char *format[,argument,...]);scanf()函数是通用终端格式化输入函数,它从标准输入设备(键盘) 读取输入的信息。可以读入任何固有类型的数据并自动把数值变换...函数名: scanf
功 能: 执行格式化输入
用 法: int scanf(char *format[,argument,...]);
scanf()函数是通用终端格式化输入函数,它从标准输入设备(键盘) 读取输入的信息。可以读入任何固有类型的数据并自动把数值变换成适当的机内格式。
其调用格式为: scanf("<格式化字符串>",<地址表>);
scanf()函数返回成功赋值的数据项数,出错时则返回EOF。
其控制串由三类字符构成:
1。格式化说明符;
2。空白符;
3。非空白符;(A) 格式化说明符
格式字符 说明
%a 读入一个浮点值(仅C99有效)
%A 同上
%c 读入一个字符
%d 读入十进制整数
%i 读入十进制,八进制,十六进制整数
%o 读入八进制整数
%x 读入十六进制整数
%X 同上
%c 读入一个字符
%s 读入一个字符串
%f 读入一个浮点数
%F 同上
%e 同上
%E 同上
%g 同上
%G 同上
%p 读入一个指针
%u 读入一个无符号十进制整数
%n 至此已读入值的等价字符数
%[] 扫描字符集合
%% 读%符号附加格式说明字符表
修饰符 说明
L/l 长度修饰符 输入"长"数据
h 长度修饰符 输入"短"数据
W 整型常数 指定输入数据所占宽度- 星号 空读一个数据
hh,ll同上h,l但仅对C99有效。
(B) 空白字符
空白字符会使scanf()函数在读操作中略去输入中的一个或多个空白字符,空白符可以是space,tab,newline等等,直到第一个非空白符出现为止。
(C) 非空白字符
一个非空白字符会使scanf()函数在读入时剔除掉与这个非空白字符相同的字符。注:scanf()控制串知识就介绍到这里(应该比较齐全了^_^),如有遗漏下次补上。下面将结合实际例程,一一阐述.
三、 scanf()函数的控制串的使用
例1.
#include "stdio.h"
int main(void)
{
int a,b,c;scanf("%d%d%d",&a,&b,&c);
printf("%d,%d,%d/n",a,b,c);
return 0;
}
运行时按如下方式输入三个值:
3□4□5 ↙(输入a,b,c的值)
3,4,5 (printf输出的a,b,c的值)
(1) &a、&b、&c中的&是地址运算符,分别获得这三个变量的内存地址。
(2) "%d%d%d"是按十进值格式输入三个数值。输入时,在两个数据之间可以用一个或多个空格、tab键、回车键分隔。
以下是合法输入方式:
① 3□□4□□□□5↙
② 3↙
4□5↙
③ 3(tab键)4↙
5↙例2.
#include "stdio.h"
int main(void)
{
int a,b,c;
scanf("%d,%d,%d",&a,&b,&c);
printf("%d,%d,%d/n",a,b,c);
return 0;
}
运行时按如下方式输入三个值:
3,4,5 ↙(输入a,b,c的值)
或者
3,□4,□5 ↙(输入a,b,c的值)
3,□□□4,□5 ↙(输入a,b,c的值)
......
都是合法的,但是","一定要跟在数字后面,如:
3□,4,□5 ↙就非法了,程序出错。(解决方法与原因后面讲)
再如:
1、sacnf()中的变量必须使用地址。
int a, b;
scanf("%d%d",a,b); //错误
scanf("%d%d",&a,&b);
2、scanf()的格式控制串可以使用其它非空白字符,但在输入时必须输入这些字符。
例:
scanf("%d,%d",&a,&b);
输入: 3,4 ↙(逗号与"%d,%d"中的逗号对应)
scanf("a=%d,b=%d",&a,&b);
输入: a=3,b=4 ↙("a=","b=",逗号与"%d,%d"中的"a=","b="及逗号对应)3、在用"%c"输入时,空格和“转义字符”均作为有效字符。
例:
scanf("%c%c%c",&c1,&c2,&c3);
输入:a□b□c↙
结果:a→c1,□→c2,b→c3 (其余被丢弃)scanf()函数接收输入数据时,遇以下情况结束一个数据的输入:(不是结束该scanf函数,scanf函数仅在每一个数据域均有数据,并按回车后结束)。
① 遇空格、“回车”、“跳格”键。
② 遇宽度结束。
③ 遇非法输入。
问题二:scanf()函数不能正确接受有空格的字符串?如: I love you!#include <stdio.h>
int main()
{
char str[80];scanf("%s",str); printf("%s",str); return 0;
}
输入:I live you!
输出:I
scanf()函数接收输入数据时,遇以下情况结束一个数据的输入:(不是结束该scanf函数,scanf函数仅在每一个数据域均有数据,并按回车后结束)。
① 遇空格、“回车”、“跳格”键。
② 遇宽度结束。
③ 遇非法输入。
所以,上述程序并不能达到预期目的,scanf()扫描到"I"后面的空格就认为对str的赋值结束,并忽略后面的"love you!".这里要注意是"love you!"还在键盘缓冲区(关于这个问题,网上我所见的说法都是如此,但是,我经过调试发现,其实这时缓冲区字符串首尾指针已经相等了,也就是说缓冲区清空了,scanf()函数应该只是扫描stdin流,这个残存信息是在stdin中)。我们改动一下上面的程序来验证一下:
#include <stdio.h>
int main()
{
char str[80];
char str1[80];
char str2[80];scanf("%s",str);/*此处输入:I love you! */ printf("%s",str); sleep(5);/*这里等待5秒,告诉你程序运行到什么地方*/ scanf("%s",str1);/*这两句无需你再输入,是对键盘盘缓冲区再扫描 */ scanf("%s",str2);/*这两句无需你再输入,是对键盘盘缓冲区再扫描 */ printf("/n%s",str1); printf("/n%s",str2); return 0;
}
输入:I love you!
输出:I
love
you!
好了,原因知道了,那么scanf()函数能不能完成这个任务?回答是:能!别忘了scanf()函数还有一个 %[] 格式控制符(如果对%[]不了解的请查看本文的上篇),请看下面的程序:
#include "stdio.h"
int main()
{
char string[50];/*scanf("%s",string);不能接收空格符*/ scanf("%[^/n]",string); printf("%s/n",string); return 0;
}
问题三:键盘缓冲区残余信息问题#include <stdio.h>
int main()
{
int a;
char c;
do
{
scanf("%d",&a);
scanf("%c",&c);
printf("a=%d c=%c/n",a,c);
/printf("c=%d/n",c);/
}while(c!='N');
}
scanf("%c",&c);这句不能正常接收字符,什么原因呢?我们用printf("c=%d/n",c);将C用int表示出来,启用printf("c=%d/n",c);这一句,看看scanf()函数赋给C到底是什么,结果是 c=10 ,ASCII值为10是什么?换行即/n.对了,我们每击打一下"Enter"键,向键盘缓冲区发去一个“回车”(/r),一个“换行"(/n),在这里/r被scanf()函数处理掉了(姑且这么认为吧^_^),而/n被scanf()函数“错误”地赋给了c.
解决办法:可以在两个scanf()函数之后加个fflush(stdin);,还有加getch(); getchar();也可以,但是要视具体scanf()语句加那个,这里就不分析了,读者自己去摸索吧。但是加fflush(stdin);不管什么情况都可行。
函数名: fflush
功 能: 清除一个流
用 法: int fflush(FILE stream);
#include <stdio.h>
int main()
{
int a;
char c;
do
{
scanf("%d",&a);
fflush(stdin);
scanf("%c",&c);
fflush(stdin);
printf("a=%d c=%c/n",a,c);
}while(c!='N');
}
这里再给一个用“空格符”来处理缓冲区残余信息的示例:
运行出错的程序:
#include <stdio.h>
int main()
{
int i;
char j;
for(i = 0;i < 10;i++)
{
scanf("%c",&j);/这里%前没有空格/
}
}
使用了空格控制符后:
#include <stdio.h>
int main()
{
int i;
char j;
for(i = 0;i < 10;i++)
{
scanf(" %c",&j);/注意这里%前有个空格/
}
}
可以运行看看两个程序有什么不同。
问题四 如何处理scanf()函数误输入造成程序死锁或出错?
#include <stdio.h>
int main()
{
int a,b,c; /计算a+b/
scanf("%d,%d",&a,&b);
c=a+b;
printf("%d+%d=%d",a,b,c);
}
如上程序,如果正确输入a,b的值,那么没什么问题,但是,你不能保证使用者每一次都能正确输入,一旦输入了错误的类型,你的程序不是死锁,就是得到一个错误的结果,呵呵,这可能所有人都遇到过的问题吧?
解决方法:scanf()函数执行成功时的返回值是成功读取的变量数,也就是说,你这个scanf()函数有几个变量,如果scanf()函数全部正常读取,它就返回几。但这里还要注意另一个问题,如果输入了非法数据,键盘缓冲区就可能还个有残余信息问题。
正确的例程:
#include <stdio.h>
int main()
{
int a,b,c; /计算a+b*/
while(scanf("%d,%d",&a,&b)!=2)fflush(stdin);
c=a+b;
printf("%d+%d=%d",a,b,c);
}scanf函数探讨
1.空白符问题
#include <stdio.h>
main()
{
int a;
printf( "input the data/n ");
scanf( "%d/n ",&a);//这里多了一个回车符/n
printf( "%d ",a);
return 0;
}
结果要输入两个数程序才结束,而不是预期的一个。why?
原因:用空白符结尾时,scanf会跳过空白符去读下一个字符,所以你必须再输入一个数。这里的空白符包括空格,制表符,换行符,回车符和换页符。所以如果你用scanf( "%d ",&a)也会出现同样的问题。
解决方法:这种错误大多是输入的时候不小心,多注意一点就好了。这种问题也不好检查,编译没有问题,一个空格也不容易看出来。当你的程序出现上面的问题时,自己对照检查一下就可以了。
2.缓冲区问题
这是一个非常容易错的地方,我就错过多次。
#include <stdio.h>
main()
{
int n = 5;
char c[n];
for(int i = 0; i < n; i++)
c[i] = scanf( "%c ",&c[i]);
printf(c);
return 0;
}
如果输入:
a
b
c
那么循环就会“提前”结束了.
原因:输入a和第一个回车后,a和这个回车符都留在缓冲区中。第一个scanf读取了a,但是输入缓冲区里面还留有一个/n,第二个scanf读取这个/n。然后输入b和第二个回车,同样的,第三个scanf读取了b,第四个
scanf读取了第二个回车符。第五个读取了c。所以五个scanf都执行了,并没有提前结束。只不过有的scanf
读取到了回车符而已。
解决方法:把程序改成这样就可以了:
for( i = 0; i < n; i++){
scanf( "%c ",&c[i]);
fflush(stdin);//刷新缓冲区
}
或者不用scanf,而用gets()函数,如:
#include <stdio.h>
main()
{
char c[5];
gets(c);
printf(c);
return 0;
}
但要注意:这个函数自动把你最后敲的回车转换为字符 '/0 '。如果你的输入超过了数组的大小,那么就会产生错误。
3.scanf()函数的参数输入类型不匹配问题
这是我在csdn论坛上见到的问题,这个错误有时候会让人莫名其妙。
#include <stdio.h>
main()
{
int a=123;
char c= 't ';
printf( "input/n ");
scanf( "%d%c ",&a,&c);
scanf( "%d%c ",&a,&c);
scanf( "%d%c ",&a,&c);
printf( "%d/n%c/n ",a,c);
return 0;
}
当输入a 回车 后,会直接跳过下面2个scanf语句,直接输出为
123
t
原因:对于scanf( "%d%c ",&a,&c),scanf语句执行时,首先试图从缓冲区中读入一个%d类型的数据,如果和第一个参数匹配,则继续从缓冲区中读取数据和第二个参数进行匹配,依次进行下去,直到匹配完所有的参
数;如果其中有一个参数不匹配,那就从这个地方跳出,忽略这个scanf后面所有的参数,而去执行下一条语
句。
可以用下面的程序验证一下:
#include <stdio.h>
int main()
{
int a=123,b=1;
char c= 't ';
scanf( "%d%d ",&a,&b);
scanf( "%c ",&c);
printf( "%d/n%d/n%c/n ",a,b,c);
return 0;
}输入:2 回车a 回车
结果是:
2
1
a
解决方法:scanf()函数执行成功时的返回值是成功读取的变量数,也就是说,你这个scanf()函数有几个变量,如果scanf()函数全部正常读取,它就返回几。但这里还要注意另一个问题,如果输入了非法数据,键盘缓
冲区就可能还个有残余信息问题。
比如:
#include <stdio.h>
main()
{
int a=123,b;
while(scanf( "%d%d ",&a,&b)!=2)
fflush(stdin);
printf( "%d/n%d/n ",a,b);
return 0;
}
你可以试一下,如果输入不是数字时,会有什么反应。补充:scanf中一种很少见但很有用的转换字符:[...]和[ ^...]。
#include <stdio.h>
main()
{
char strings[100];
scanf( "%[1234567890] ",strings);
printf( "%s ",strings);
return 0;
}
运行,输入:1234werew后,结果是:1234。
通过运行可以发现它的作用是:如果输入的字符属于方括号内字符串中某个字符,那么就提取该字符;如果一经发现不属于就结束提取。该方法会自动加上一个字符串结束符到已经提取的字符后面。
scanf( "%[^1234567890] ",strings); 它的作用是:如果一经发现输入的字符属于方括号内字符串中某个字符,那么就结束提取;如果不属于就提取该字符。该方法会自动加上一个字符串结束符到已经提取的字符后面
。
注意:方括号两边不能空格,如:scanf( "%[ 1234567890 ] ",strings); scanf( "%[ ^1234567890] ",strings); 不让空格也会算在里面的。
用这种方法还可以解决scanf的输入中不能有空格的问题。只要用
scanf( "%[^/n] ",strings); 就可以了。很神奇吧。scanf原型:参见《C语言大全》和K&C
include <stdio.h> ;
int scanf( const char *format, ... );
函数 scanf() 是从标准输入流 stdin 中读内容的通用子程序,可以读入全部固有类型的数据并自动转换成机内形式。在 C99 中,format 用 restrict 修饰。
format 指向的控制串由以下三类字符组成:
● 格式说明符
● 空白符
● 非空白符转换字符(就是%后跟的部分)
a 读浮点值(仅适用于 C99)
A 读浮点值(仅适用于 C99)
c 读单字符
d 读十进制整数
i 读十进制、八进制、十六进制整数
e 读浮点数
E 读浮点数
f 读浮点数
F 读浮点数(仅适用于 C99)
g 读浮点数
G 读浮点数
o 读八进制数
s 读字符串
x 读十六进制数
X 读十六进制数
p 读指针值
n 至此已读入值的等价字符数
u 读无符号十进制整数
[ ] 扫描字符集合
% 读 % 符号(百分号)例如: %s 表示读串而 %d 表示读整数。格式串的处理顺序为从左到右,格式说明符逐一与变元表中的
变元匹配。为了读取长整数,可以将 l(ell) 放在格式说明符的前面;为了读取短整数,可以将 h 放在格式
说明符的前面。这些修饰符可以与 d、i、o、u 和 x 格式代码一起使用。
默认情况下,a、f、e 和 g 告诉 scanf() 为 float 分配数据。 如果将 l(ell) 放在这些修饰符的前
面,则 scanf() 为 double 分配数据。使用 L 就是告诉 scanf(),接收数据的变量是 long double 型变量。
如果使用的现代编译器程序支持 1995 年增加的宽字符特性, 则可以与 c 格式代码一起,用 l 修饰符
说明类型 wchar_t 的宽字符指针;也可以与 s 格式代码一起,用 l 修饰符说明宽字符串的指针。l 修饰符
也可以用于修饰扫描集,以说明宽字符。
控制串中的空白符使 scanf() 在输入流中跳过一个或多个空白行。空白符可以是空格(space)、制表符
(tab)和新行符(newline)。 本质上,控制串中的空白符使 scanf() 在输入流中读,但不保存结果,直到发
现非空白字符为止。
非空白符使 scanf() 在流中读一个匹配的字符并忽略之。例如, "%d,%d " 使 scanf() 先读入一个整数
,读入中放弃逗号,然后读另一个整数。如未发现匹配,scanf() 返回。
scanf() 中用于保存读入值的变元必须都是变量指针,即相应变量的地址。
在输入流中,数据项必须由空格、制表符和新行符分割。逗号和分号等不是分隔符,比如以下代码:
scanf( "%d %d ", &r, &c );
将接受输入 10 20,但遇到 10,20 则失败。百分号(%)与格式符之间的星号()表示读指定类型的数据但不保存。因此,
scanf( "%d %c %d ", &x, &y );
对 10/20 的读入操作中,10 放入变量 x,20 放入 y。格式命令可以说明最大域宽。 在百分号(%)与格式码之间的整数用于限制从对应域读入的最大字符数。
例如,希望向 address 读入不多于 20 个字符时,可以书写成如下形式:
scanf( "%20s ", address );如果输入流的内容多于 20 个字符,则下次 scanf() 从此次停止处开始读入。 若达到最大域宽前已遇
到空白符,则对该域的读立即停止;此时,scanf() 跳到下一个域。
虽然空格、制表符和新行符都用做域分割符号,但读单字符操作中却按一般字符处理。例如,对输入流
"x y " 调用:
scanf( "%c%c%c ", &a, &b, &c );
返回后,x 在变量 a 中,空格在变量 b 中,y 在变量 c 中。注意,控制串中的其它字符,包括空格、制表符和新行符,都用于从输入流中匹配并放弃字符,被匹配
的字符都放弃。例如,给定输入流 "10t20 ",调用:
scanf( "%dt%d ", &x, &y );
将把 10 和 20 分别放到 x 和 y 中,t 被放弃,因为 t 在控制串中。ANSI C 标准向 scanf() 增加了一种新特性,称为扫描集(scanset)。 扫描集定义一个字符集合,可由
scanf() 读入其中允许的字符并赋给对应字符数组。 扫描集合由一对方括号中的一串字符定义,左方括号前
必须缀以百分号。 例如,以下的扫描集使 scanf() 读入字符 A、B 和 C:
%[ABC]使用扫描集时,scanf() 连续吃进集合中的字符并放入对应的字符数组,直到发现不在集合中的字符为
止(即扫描集仅读匹配的字符)。返回时,数组中放置以 null 结尾、由读入字符组成的字符串。
用字符 ^ 可以说明补集。把 ^ 字符放为扫描集的第一字符时,构成其它字符组成的命令的补集合,指
示 scanf() 只接受未说明的其它字符。
对于许多实现来说,用连字符可以说明一个范围。 例如,以下扫描集使 scanf() 接受字母 A 到 Z:
%[A-Z]
重要的是要注意扫描集是区分大小写的。因此,希望扫描大、小写字符时,应该分别说明大、小写字母。
scanf() 返回等于成功赋值的域数的值,但由于星号修饰符而读入未赋值的域不计算在内。给第一个域赋值前已出错时,返回 EOF。
C99 为 scanf() 增加了几个格式修饰符:hh、ll、j、z 和 t。hh 修饰符可用于 d、i、o、u、x、X 或
n。它说明相应的变元是 signed 或 unsigned char 值,或用于 n 时, 相应的变元是指向 long char 型变
量的指针。ll 修饰符也可用于 d、i、o、u、x、X 或 n。它说明相应的变元是 signed 或者 unsigned long
long int 值。
j 格式修饰符应用于 d、i、o、u、x、X 或 n,说明匹配的变元是类型 intmax_t 或 uintmax_t。这些类型在 <stdint.h> ; 中声明,并说明最大宽度的整数。
z 格式修饰符应用于 d、i、o、u、x、X 或 n,说明匹配的变元是指向 size_t 类型对象的指针。该类型在 <stddef.h> ; 中声明,并说明 sizeof 的结构。
t 格式修饰符应用于 d、i、o、u、x、X 或 n,说明匹配的变元是指向 ptrdiff_t 类型对象的指针。该类型在 <stddef.h> ; 中声明,并说明两个指针之间的差别。
例子:
include <stdio.h> ;
int main( void )
{
char str[80], str2[80];
int i;
/ read a string and a integer /
scanf( "%s%d ", str, &i );
/ read up to 79 chars into str /
scanf( "%79s ", str );
/ skip the integer between the two strings /
scanf( "%s%*d%s ", str, str2 );
return 0;
}你的问题在这个部分:
3.scanf()函数的参数输入类型不匹配问题
这是我在csdn论坛上见到的问题,这个错误有时候会让人莫名其妙。
#include <stdio.h>
main()
{
int a=123;
char c= 't ';
printf( "input/n ");
scanf( "%d%c ",&a,&c);
scanf( "%d%c ",&a,&c);
scanf( "%d%c ",&a,&c);
printf( "%d/n%c/n ",a,c);
return 0;
}
当输入a 回车 后,会直接跳过下面2个scanf语句,直接输出为
123
t
原因:对于scanf( "%d%c ",&a,&c),scanf语句执行时,首先试图从缓冲区中读入一个%d类型的数据,如果和第一个参数匹配,则继续从缓冲区中读取数据和第二个参数进行匹配,依次进行下去,直到匹配完所有的参
数;如果其中有一个参数不匹配,那就从这个地方跳出,忽略这个scanf后面所有的参数,而去执行下一条语
句。
可以用下面的程序验证一下:
#include <stdio.h>
int main()
{
int a=123,b=1;
char c= 't ';
scanf( "%d%d ",&a,&b);
scanf( "%c ",&c);
printf( "%d/n%d/n%c/n ",a,b,c);
return 0;
}输入:2 回车a 回车
结果是:
2
1
a
解决方法:scanf()函数执行成功时的返回值是成功读取的变量数,也就是说,你这个scanf()函数有几个变量,如果scanf()函数全部正常读取,它就返回几。但这里还要注意另一个问题,如果输入了非法数据,键盘缓
冲区就可能还个有残余信息问题。
比如:
#include <stdio.h>
main()
{
int a=123,b;
while(scanf( "%d%d ",&a,&b)!=2)
fflush(stdin);
printf( "%d/n%d/n ",a,b);
return 0;
}转载于:https://blog.51cto.com/14058389/2337037
- 星号 空读一个数据
-
C语言scanf函数用法完全攻略
2021-05-21 14:33:08本节介绍输入函数 scanf 的用法。scanf 和 printf一样,非常重要,而且用得非常多,所以一定要掌握。概述scanf的功能用一句话来概括就是“通过键盘给程序中的变量赋值”。该函数的原型为:# includeint scanf(const ...本节介绍输入函数 scanf 的用法。scanf 和 printf
一样,非常重要,而且用得非常多,所以一定要掌握。
概述
scanf
的功能用一句话来概括就是“通过键盘给程序中的变量赋值”。该函数的原型为:
# include
int scanf(const char *format, ...);
它有两种用法,或者说有两种格式。
1) scanf("输入控制符", 输入参数);
功能:将从键盘输入的字符转化为“输入控制符”所规定格式的数据,然后存入以输入参数的值为地址的变量中。
下面给大家举个例子:
#include
int
main(void)
{
int
i;
i =
10;
printf("i = %d\n", i);
return
0;
}
我们前面都是像这样写的,即直接给变量 i
赋一个值。但是这样写功能比较弱,因为这个值就变成一个“死值”了,它只能是
10,不可能是其他值,除非在程序中修改。很多时候我们希望这个值不是由程序员在程序中指定的,而是在程序运行的过程中由用户从键盘输入的。用户输入多少,变量i就是多少,这样程序的功能就更加灵活了。
那么如何实现在程序运行的过程中由用户从键盘输出值呢?用 scanf 即可实现:
#
include
int
main(void)
{
int
i;
scanf("%d", &i); //&i 表示变量 i
的地址,&是取地址符
printf("i = %d\n", i);
return
0;
}
“输入控制符”和“输出控制符”是一模一样的。比如一个整型数据,通过 printf
输出时用%d输出,通过 scanf 输入时同样是用%d。
要想将程序中的 scanf
行弄明白,首先要清楚的是:我们从键盘输入的全部都是字符。比如从键盘输入 123,它表示的并不是数字 123,而是字符 '1'、字符
'2' 和字符 '3'。这是为什么呢?
操作系统内核就是这样运作的。操作系统在接收键盘数据时都将它当成字符来接收的。这时就需要用“输入控制符”将它转化一下。%d的含义就是要将从键盘输入的这些合法的字符转化成一个十进制数字。经过 %d 转化完之后,字符
123 就是数字 123 了。
第二个要弄清楚的是:&是一个取地址运算符,&后面加变量名表示“该变量的地址”,所以&i就表示变量 i 的地址。&i又称为“取地址i”,就相当于将数据存入以变量 i
的地址为地址的变量中。
那么以变量 i 的地址为地址的变量是哪个变量呢?就是变量 i。所以程序中 scanf
的结果就把值 123 放到变量i中。
综上所述,scanf 语句的意思就是:从键盘上输入字符
123,然后%d将这三个字符转化成十进制数 123,最后通过“取地址 i”找到变量 i 的地址,再将数字
123 放到以变量 i 的地址为地址的变量中,即变量 i 中,所以最终的输出结果就是i=123。
注意,为什么不直接说“放到变量i中”?而是说“放到以变量 i
的地址为地址的变量中”?因为这么说虽然很绕口,但是能加强对 &i 的理解,这么说更能表达 &i
的本质和内涵。很多人在学习 scanf 的时候,经常将“变量 i”和“变量 i 的地址”混淆,从而思维开始混乱,等深刻了解
&i 的含义之后就可以不那么说了。
以上是 scanf 的最简单用法,也是最常用、最基本、最重要的用法。这样通过 scanf
就可以在程序运行的过程中由用户来指定变量 i 的值,这与在程序中赋值相比较功能更强大。
2) scanf("输入控制符非输入控制符",
输入参数);
这种用法几乎是不用的,也建议你们永远都不要用。但是经常有人问,为什么 printf
中可以有“非输出控制符”,而 scanf
中就不可以有“非输入控制符”。事实上不是不可以有,而是没有必要!下面来看一个程序:
#
include
int
main(void)
{
int
i;
scanf("i = %d", &i);
printf("i = %d\n", i);
return
0;
}
在 printf 中,所有的“非输出控制符”都要原样输出。同样,在 scanf
中,所有的“非输入控制符”都要原样输入。所以在输入的时候i=必须要原样输入。比如要从键盘给变量 i 赋值
123,那么必须要输入i=123才正确,少一个都不行,否则就是错误。
所以 scanf 中%d后面也没有必要加\n,因为在 scanf 中\n不起换行的作用。它不但什么作用都没有,你还要原样将它输入一遍。
所以在 scanf
的使用中一定要记住:双引号内永远都不要加“非输入控制符”。除了“输入控制符”之外,什么都不要加,否则就是自找麻烦。而且对于用户而言,肯定是输入越简单越好。
一次给多个变量赋值:
#
include
int
main(void)
{
int
i,
j;
scanf("%d%d", &i, &j);
printf("i = %d, j = %d\n", i, j);
return
0;
}
首先,scanf
中双引号内除了“输入控制符”之外不要加任何“非输入控制符”。通过键盘给多个变量赋值与给一个变量赋值其实是一样的。比如给两个变量赋值就写两个
%d,然后“输入参数”中对应写上两个“取地址变量”;给三个变量赋值就写三个
%d,然后“输入参数”中对应写上三个“取地址变量”……
但是需要注意的是,虽然 scanf
中没有加任何“非输入控制符”,但是从键盘输入数据时,给多个变量赋的值之间一定要用空格、回车或者 Tab
键隔开,用以区分是给不同变量赋的值。而且空格、回车或 Tab
键的数量不限,只要有就行。一般都使用一个空格。
此外强调一点:当用 scanf 从键盘给多个变量赋值时,scanf
中双引号内多个“输入控制符”之间千万不要加逗号,。
有些人觉得在输入的时候可以用逗号分隔,所以就在“输入控制符”之间用逗号隔开。这样做从程序的角度确实是可以的,但是建议大家不要这样做。在实际编程中这种写法是绝对不允许的,原因有两个:
首先逗号要原样输入的,有几个就要输入几个,少一个或多一个都不行;
其次,也是最主要的原因就是输入法的问题,在 scanf
中是在英文输入法下写的逗号,那么输入的时候如果是中文输入法下的逗号那也是错的。所以用逗号很容易出错。
最后再次强调:scanf“输入参数”的取地址符&千万不要忘了。这是初学者经常犯的错误。而 printf
中的“输出参数”是不带取地址符的,不要混淆了。
使用scanf的注意事项
1) 参数的个数一定要对应
在前面介绍 printf
时说过,“输出控制符”和“输出参数”无论在“顺序上”还是在“个数上”一定要一一对应。这句话同样对 scanf
有效,即“输入控制符”和“输入参数”无论在“顺序上”还是在“个数上”一定要一一对应。比如:
#
include
int
main(void)
{
char
ch;
int
i;
scanf("%c%d", &ch);
printf("ch = %c, i =
%d\n", ch, i);
return
0;
}
在 VC++6.0
中的输出结果是:
a 6
ch = a, i = -858993460
这种错误是初学者经常犯的,由于粗心大意,少写一个参数。更严重的是,这种错误在编译的时候不会报错。printf
也是一样,即使“输出参数”少写了也不会报错,但从程序的功能上讲这么写就是错的。所以在编程的时候一定要避免这种错误的发生。
程序中为什么 i=–858993460?这个在《为什么要初始化变量》中讲过,当变量没有初始化的时候就会输出这个值。
在后面会讲到 scanf
是缓冲输入的,也就是说从键盘输入的数据都会先存放在内存中的一个缓冲区。只有按回车键后 scanf
才会进入这个缓冲区和取数据,所取数据的个数取决于 scanf 中“输入参数”的个数。所以上述程序中 scanf
只有一个输入参数,因此按回车键后 scanf 只会取一个数据。所以变量 ch 有数据,而变量 i
没有数据,没有数据就是没有初始化,输出就是 –858993460。
2) 输入的数据类型一定要与所需要的数据类型一致
在 printf 中,“输出控制符”的类型可以与数据的类型不一致,如:
#
include
int
main(void)
{
int
i =
97;
printf("i = %c\n", i);
return
0;
}
在 VC++ 6.0 中的输出结果是:
i = a
但是在 scanf 中,对于从键盘输入的数据的类型、scanf
中“输入控制符”的类型、变量所定义的类型,这三个类型一定要一致,否则就是错的。虽然编译的时候不会报错,但从程序功能的角度讲就是错的,则无法实现我们需要的功能。比如:
#
include
int
main(void)
{
int
i;
scanf("%d", &i);
printf("i = %d\n", i);
return
0;
}
在 VC++ 6.0 中的输出结果是:
a
i = -858993460
输出 –858993460 表示变量未初始化。为什么输入 a,变量 i
却显示未初始化呢?
在 scanf 中,从键盘输入的一切数据,不管是数字、字母,还是空格、回车、Tab
等字符,都会被当作数据存入缓冲区。存储的顺序是先输入的排前面,后输入的依次往后排。按回车键的时候 scanf
开始进入缓冲区取数据,从前往后依次取。
但 scanf 中 %d 只识别“十进制整数”。对 %d 而言,空格、回车、Tab
键都是区分数据与数据的分隔符。当 scanf 进入缓冲区中取数据的时候,如果 %d 遇到空格、回车、Tab
键,那么它并不取用,而是跳过继续往后取后面的数据,直到取到“十进制整数”为止。对于被跳过和取出的数据,系统会将它从缓冲区中释放掉。未被跳过或取出的数据,系统会将它一直放在缓冲区中,直到下一个
scanf 来获取。
但是如果 %d
遇到字母,那么它不会跳过也不会取用,而是直接从缓冲区跳出。所以上面这个程序,虽然 scanf 进入缓冲区了,但用户输入的是字母
a,所以它什么都没取到就出来了,而变量 i 没有值,即未初始化,所以输出就是 –858993460。
但如果将 %d 换成 %c,那么任何数据都会被当作一个字符,不管是数字还是空格、回车、Tab
键它都会取回。
不但如此,前面讲过,你从键盘输入 123,这个不是数字 123,而是字符 '1'、字符
'2' 和字符 '3',它们依次排列在缓冲区中。因为每个字符变量 char 只能放一个字符。所以输入“123”之后按回车,scanf
开始进入缓冲区,按照次序,先取字符 '1',如果还要取就再取字符 '2',以此类推。
如果都取完了还有 scanf
要取数据,那么用户就需要再输入。先写一个程序看一下:
#
include
int
main(void)
{
char
i,
j,
k;
scanf("%c%c%c", &i, &j, &k);
printf("i = %c, j = %c, k =
%c\n", i, j, k);
return
0;
}
在 VC++ 6.0 中的输出结果是:
123
i = 1, j = 2, k = 3
从这个程序中我们看出,就单纯地输入
123,不加任何空格,按回车键之后就同我们所讲的一样,分别将字符 '1'、字符 '2' 和字符 '3' 赋给字符变量 i、j 和
k。
但是需要提醒大家注意的是,在之前程序中,因为 scanf 是 %d,所以 a
没有被取出来,还在缓冲区中。当遇到下一个 scanf 是 %c 时它就会被取出来。但是如果一直没有出现
%c,那么这时就会出现一个问题:scanf怎么取十进制整数?即使使用 %d,但是由于字符 a “挡”在最前面,scanf
进去先碰到的总是 a,也就无法取到它后面的整数,所以必须先将
a“弄走”。这就牵涉到“清空输入缓冲区”的概念,这个稍后再讲。
3) 在使用 scanf 之前使用 printf
提示输入
大家想一想,前面写的 scanf 程序有没有不足的地方?
程序写好之后,编译、链接、执行,然后弹出黑窗口,出现一个光标在那不停地闪。对于编写程序的人来说他知道要输入什么,但是对于用户而言,用户怎么知道是什么意思呢?所以之前的程序都缺少提示信息!因此在使用scanf之前,最好先用printf提示用户以什么样的方式输入,这样可以大大提高代码的质量。看看下面这个程序:
#
include
int
main(void)
{
int
i,
j;
printf("请输入两个值,中间以空格分隔:");
scanf("%d%d", &i, &j);
printf("i = %d, j = %d\n", i, j);
return
0;
}
这样在执行的时候,用户一看就知道是要输入两个值,然后中间用空格隔开。所以这样写就更人性化、智能化了。
小结
scanf
的使用看似细节繁杂,但使用起来非常简单。就目前而言,只要掌握以下五点:
在 scanf
的“输入参数”中,变量前面的取地址符&不要忘记。
scanf 中双引号内,除了“输入控制符”外什么都不要写。
“输出控制符”和“输出参数”无论在“顺序上”还是在“个数上”一定要一一对应。
“输入控制符”的类型和变量所定义的类型一定要一致。对于从键盘输入的数据的类型,数据是用户输入的,程序员是无法决定的,所以在写程序时要考虑容错处理,这个稍后再讲。
使用 scanf 之前先用 printf 提示输入。
只要掌握了以上五点,scanf
的使用基本上就没什么问题了。至于其他注意点,到后面讲数组和指针的时候再介绍。
-
C语言教学中scanf函数用法研究.pdf
2021-09-19 14:25:42C语言教学中scanf函数用法研究.pdf -
scanf()函数的用法
2019-03-07 15:57:561 scanf()函数简介 scanf()函数的作用是从标准的输入流中读取数据,并将读取到的数据保存到指定的变量中。其格式为 int scanf( const char *format [, argument]... ); 其中,参数format指定了读取数据的方式;... -
C语言中Scanf函数的用法
2019-07-11 00:11:06Scanf函数是C语言中的一个输入函数,它的功能是**给程序中的变量赋值**。 -
printf函数和scanf函数,C语言printf函数和scanf函数详解
2021-05-22 10:29:31对于 printf 函数,相信大家并不陌生。之所以称它为格式化输出函数,关键就是该函数可以按用户指定的格式,把指定的数据显示到显示器屏幕上。该函数原型的一般格式如下:int printf(const char * format, ... );很... -
C语言基础知识(2): scanf函数用法
2020-04-02 21:30:05scanf 函数功能:按用户指定的格式从键盘上把数据...scanf 函数基本用法: scanf(“输入控制符”, 输入参数); //用法1 将键盘输入的字符转化为输入控制符所规定的格式的数据, //然后,存入以输入参数的值为地址... -
scanf的用法
2015-09-22 16:41:39SCANF 函数 使用方法 -
C语言scanf函数用法详细解释!!!
2017-12-21 19:20:03函数名: scanf 功 能: 执行格式化输入 用 法: int scanf(char *format[,argument,...]); scanf()函数是通用终端格式化输入函数,它从标准输入设备(键盘) 读取输入的信息。可以读入任何固有类型的数据并自动把... -
C语言scanf函数用法详细解释
2018-03-12 15:28:53本文为转载,原博客地址:...scanf()函数是通用终端格式化输入函数,它从标准输入设备(键盘) 读取输入的信息。可以读入任何固有类型的数据并自动把数值变换... -
C语言中scanf函数详解
2020-05-24 14:46:031. scanf函数的使用公式 scanf是一个变参函数。(参数的数量和类型不确定) scanf的第一个参数是字符串。 scanf的第一个参数是需要输入的字符串以及需要被读取的占位符。 scanf的后续参数,是依次被读取并赋值的变量... -
scanf函数使用
2020-07-31 02:07:51scanf函数使用scanf函数解决问题问题一问题二 来自https://blog.csdn.net/liuuze5/article/details/51098471 scanf函数 函数原型 int scanf(const char *format,...); 调用形式:scanf("<格式说明字符串>",&... -
C C++ Scanf函数的用法.
2011-02-10 12:58:23使用Scanf时经常用到的一些知识点,因为不容易记,所以总结到了一起。 -
C语言Scanf函数
2021-05-21 01:46:00C语言的scanf函数一、变量的内存分析(一)字节与地址①.内存以字节为单位 每个字节都有自己的内存地址,根据地址就可以找到该字节。整个内存相当于一整个酒店,而酒店以房间为单位,在这里每个房间就相当于是每个字节... -
C++使用 scanf函数
2019-06-06 15:17:00所以在使用scanf()的时候需要加下面这段在头文件 顶部: #define _CRT_SECURE_NO_WARNINGS 测试代码求质数: #define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespac... -
stm32编程中实现printf函数和scanf函数
2020-08-19 00:23:34///重定向 c 库函数 printf 到串口,重定向后可使用 printf 函数 int fputc(int ch, FILE *f) { /* 发送一个字节数据到串口 */ USART_SendData(USARTx, (uint8_t) ch); /* 等待发送完毕 */ while (USART_... -
如何使用scanf函数?
2020-11-30 22:00:08这scanf函数学了快10年了,怎么还会出现莫名其妙的问题?看下面的代码(VS2012环境下运行): #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> int main() { char root_value = '\0'; int i =1; while ... -
详解C语言中scanf函数使用的一些注意点
2021-03-17 11:02:13(一)基本介绍Scanf是系统自带的函数,声明包含在stdio.h文件中,因此要是有该函数,必须加载#include头文件。当执行到scanf函数时,程序就暂停等待用户输入,该函数只... 使用scanf函数输入一个字符变量。Char a; sc... -
scanf函数用法详解
2015-04-20 15:01:10scanf()函数是通用终端格式化输入函数,它从标准输入设备(键盘) 读取输入的信息。可以读入任何固有类型的数据并自动把数值变换成适当的机内格式。 其调用格式为: scanf("格式化字符串>",地址表>); sc -
scanf 函数 —— 基本的输入函数
2021-07-15 19:24:12scanf 函数的两种用法,或者说两种格式如下: 1、scanf( " 输入控制符 " ,输入参数); /* ----- 英文输入法输入 -----*/ 简单、常用用法 例如:scanf("%d", &i); /* &i 表示变量 i 的地址,&是取地址符... -
scanf函数与printf函数用法
2019-09-25 05:22:03一开始学习就是用的cin、cout,所有习惯用这个,但是后来做题发现这样的输入方式有弊端,所以决定整理熟悉一下scanf函数与printf函数。 头文件 # include <stdio.h> scanf("输入控制符",输入参数) ... -
C语言中输入函数(scanf()、fgets()和gets())的区别详解
2021-01-01 05:30:29他们的使用方法及注意事项如下: 1.scanf() 它是一种格式化的输入方式,可一次性按照规定的格式输入多个数据域。 scanf函数是一个标准库函数,它的函数原型在头文件“stdio.h”中。与printf函数相同,C语言也允许在... -
c中scanf函数用法
2019-04-04 20:40:29scanf()函数返回成功赋值的数据项数,出错时则返回EOF。 我们输入的数据大体上可以分为几个类型:: 格式化说明符 空白符*****(空白符包括 空格,制表符,换行符,回车符和换页符)***** 非... -
【自学】【C语言】【笔记】scanf函数讲解,scanf函数格式符号和格式附加符号。
2022-03-29 20:00:49scanf函数讲解,scanf函数格式符号和格式附加符号。 -
C语言scanf函数详解和示例
2020-04-11 16:04:56一、数据输入 编写程序的主要目的就是为了处理数据。数据从哪里来?数据的来源有很多种方式,如从磁盘文件中读取数据、从数据库中读取数据、从网页...scanf:格式化输入函数,一次可以输入多个数据,保存到多个变量... -
printf函数 + scanf函数
2021-09-14 16:38:323.1 printf函数 ①printf函数显示格式串的内容,并可在该串中指定位置插入值。...转换说明以 % 开头, % 后面的信息指定了从内部形式(二进制)转换为打印形式(字符)的方法; ③格式串中的转换说明要