scanf语句的使用和执行原理
1、如何使用scanf:
%d说明我们现在要读入一个整数了,scanf这个函数会读入一个整数,读到的结果赋值给指定变量,要注意指定变量前面的&
scanf("%d",&price);
如果要读入输入的数据,就必须严格按照""中的格式输入,如:
scanf("%d,%d",&a,&b);
输入应为1,2,此时可以正常读取,正常输出,如图所示:
但是如果我们不严格按照""中的格式输入,读取就会出现问题,如图所示:
输入缓冲区是行缓冲区,当你按下回车之前,除非特意对缓冲区进行刷新,否则你的程序不会读到任何东西,回车符会使行缓冲区进行刷新,即回车符是输入结束的标志。虽然说输入的结束标志是回车键,但是回车键并不一定代表输入结束,如果你输入的并没有满足scanf语句读取的格式化的内容,scanf会把回车键视作一个空格。
scanf("%d %d",&a,&b);
输入格式1 2或者 1(回车)2都是对的,输入回车时还没有满足scanf语句读取的格式化的内容,因此会把回车键视作一个空格。
我们要注意下面这段代码,输入应为1 2(2的后面还应该有个任意符号来满足那个空格,唯独不能用回车符来满足这个空格,回车符作为空格被读入,但是后面输入的作为行结束标志的回车符就不会被读到程序中。
scanf("%d %d ",&a,&b);
不过我们依然可以用回车符来满足中间的那个空格,如下图所示:
同上述代码一样,2的后面随便再输入什么东西来满足这个回车号,唯独不能用回车符来满足这个最后的回车号,回车符作为空格被读入,但是后面输入的作为行结束标志的回车符不会被读到程序中。
scanf("%d %d/n",&a,&b);//输入1 2
2、scanf语句的原理
scanf并不会直接从我们的键盘输入中读取数据,我们从键盘输入的数据先存储在输入缓冲区中,当按下回车键后,即输入缓冲区遇到回车符时,会对输入缓冲区进行一个刷新,程序才会在输入缓冲区中读取数据,scanf读取到空格、tab或者回车符的时候停止读取。
例子:
int main()
{
int arr[10] = { 0 };
int i = 0;
for (i = 0; i < 10; i++)
{
scanf("%d", &arr[i]);
}
return 0;
}
上面这段代码它是如何给数组赋值的呢?
在第一次进入for循环执行到scanf语句的时候,会跳出命令行窗口,输入我们想要给数组赋的值,注意这里是一次性输入所有的值:
这些输入的值并不是直接被scanf语句读取,而是存储到输入缓冲区,当按下回车键(即输入回车符)的时候,输入缓冲区中便有了回车符,此时scanf语句开始读取输入缓冲区中的值,此时i的值为0,读取到1赋值给arr[0],读取完后scanf语句会继续读取,读取完空格后scanf语句就会停止读取,进入下一轮循环,此时i的值为1,scanf语句接着后面继续读取,就会把读取的2赋值给arr[1],然后继续读取空格,停止读取,进入下一轮循环,直到读取到回车符,停止读取,此时i的值为10,循环结束。
这个时候会有小伙伴们疑惑了,scanf每次读取完数字后,真的继续把后面的空格也读取掉了?
这里我们直接上代码调试证明一下即可。
如图所示,我们在scanf语句中的%d后面添加一个%c,看看会不会读取空格赋值给变量c1:
我们先在135行也就是for循环处设置断点,然后开始调试,监视c1,i和arr[i]的值,往下走到136行,也就是scanf语句处,此时scanf语句未执行,所以没有任何变化,再往下走,走到137行,此时scanf语句已经执行,我们在命令行窗口一次性输入需要给数组赋的值,1 2 3 4,然后按下回车键:
观察此时的arr[i]和c1:
如图所示此时arr[0]的值为1,说明scanf语句读取了数字1赋值给了arr[0],此时c1的值为32(‘ ’)说明scanf语句读取了数字1赋值给arr[0]后确实读取了后面的空格并且将其赋值给了变量c1。
这说明scanf语句读取完数字后,会把后面的空格也读取掉。如果后面有变量来接收,读取后就会把空格赋值给对应的变量,如果没有变量来接收,那么仅仅是读取,不会进行赋值操作。值得注意的是,scanf只有在读取完数字后会继续把后面的空格读取掉
我们仔细看看下面这段代码:
char word[8];
scanf("%s",word);//Hello world
printf("%s##\n",word);//Hello##
这说明读取完字符o后,并没有将后面的空格读取出来,遇到空格就直接停止读取了。
那么后面的流程大家应该都知道了,每一轮for循环,scanf语句都会读取数字赋值给数组单元,然后把后面的空格读取掉,停止读取,进入下一轮循环,但是在最后一轮循环中有些许不同,scanf读取掉4后,后面不是空格了,而是回车符,因此scanf会把后面的回车符读掉,然后停止读取,后面i自增1,i的值为4跳出循环。