一、格式化输入
1、%c:
scanf()中最为诡计多端的就是字符类型的输入了,下面编写了一个简易程序,来看看scanf()是怎么处理字符的吧~
#include<stdio.h>
int main(void)
{
int s;
char c;
while (1)
{
s = scanf_s("%c",&c);
printf("此时存入的字符是:%c\n", c);
printf("scanf_s返回值是:%d\n",s);
}
return 0;
}
(注:该程序仅为测试用,故循环没有出口。)
1)char类型占一字节,故每次不管输入多少字节,只能存入一个字节,返回值仍为1,剩余的不删除,存在缓冲区中,留着下次输入用;
2)char不跳过空白字符(退格,空格,回车),皆可存入且输出,返回值皆为1;
3)插入不能直接读取负数,会把负号和数字分开存入;
4)因为中文占两字节,所以无法成功存入,但会被拆分成两个字节分别存在参数和缓冲区中,返回值仍为1;
2、%d:
#include<stdio.h>
int main(void)
{
int s,d;
char c;
while (1)
{
s = scanf_s("%d",&d);
printf("此时存入的数字是:%d\n", d);
printf("scanf_s返回值是:%d\n",s);
}
return 0;
}
1)输入字符:存在两种情况
情况一:int d未初始化,程序将一个溢出值赋给d(我们甚至还可以对带着溢出值的d进行操作),scanf返回值为0;
情况二:假如我们给int d一个初始值,我们会发现,数值d的值不会被该溢出值改变,scanf返回值为0。
值得注意的是,无论d的值有没有被溢出值改变,无效字符q都会被扔到缓冲区中,这点我们会在下文混合输入字符和数字时看到。
3、字符与数字混合输入:
现在来看看字符和数字会摩擦出怎样的火花吧~
1)先字符后数字型:
#include<stdio.h>
int main(void)
{
int s,d;
char c;
while (1)
{
s = scanf_s("%c%d",&c,1,&d);//注意scanf_s在混合输入时要在c后面加个输入长度。
printf("此时存入的字符和数字是:%c和%d\n", c,d);
printf("scanf_s返回值是:%d\n",s);
}
return 0;
}
ps:不明白为什么要在c后面加个长度的说,c不是都是1个字节吗。。
可以看到,当输入12q时,1被存入c,2被存入d,q 和\n在缓冲区,接下来,q被存入c,但是由于%d会跳过\n,因此程序要求客户再次输入,发现了qq,因为d已经有有效值2了,故不将q对应的溢出值存在d中,并把两个q扔到缓冲区,所以我们可以发现接下来q被打印了两次。
因此scanf接受信息的顺序其实是这样的:
12\qq\qw\w?
2)先数字后字符:
#include<stdio.h>
int main(void)
{
int s,d;
char c;
while (1)
{
s = scanf_s("%d%c", &d,&c,1);//注意scanf_s在混合输入时要在c后面加个输入长度。
printf("此时存入的数字和字符是:%d和%c\n", d, c);
printf("scanf_s返回值是:%d\n", s);
}
return 0;
}
情形1:
第二个q无效,被扔到缓冲区,但是scanf的返回值为2;接下来,q不断被%d读取错误,原先的d和c的值都不被改变。
情形2:
只要前面是数字,就会被视为数字而不是字符。
情形3:
1和换行符在第一次输入时被扔到缓冲区供第二次输入使用。
3、%f:
输入字符:跟%d一样,只不过溢出值有小数点而已。
返回值:输入整型数时返回值是1。
总结:
1、scanf只有往%d或%f里打字符时返回值才为0,往%c里打数字时数字会被视为字符,没有影响,多打多余的会被扔到缓冲区里,返回值还是不受影响。
2、往%d里打字符时,若已有值,则值不改变,否则变为溢出值。
3、若用scanf_s输入多个值,要在%c后面加个,1,。
4、%d会吃掉它前面的空白字符,但是不会吃掉它后面的空白字符。
二、getchar()
1、getchar()或char c=getchar()的返回值是对应的输入字符;
2、单打getchar()可以吃掉一个字符