gets()与 scanf()的区别
⚫ gets()函数支持输入的字符串中有空格。因为 gets()函数允许输入的字符串带有空格、制表符,输入的空格和制表符也是字符串的一部分,仅以回车换行符作为字符串的分割符。
而对于 scanf 以%s 格式输入的时候,空格、换行符、TAB 制表符等都是作为字符串分割符存在,即分隔符前后是两个字符串,读取字符串时并不会将分隔符读取出来作为字符串的组成部分,一个%s 只能读取一个字符串,若要多去多个字符串,则需要使用多个%s、并且需要使用多个字符数组存储。
⚫ gets()会将回车换行符从输入缓冲区中取出来,然后将其丢弃,所以使用 gets()读走缓冲区中的字符串数据之后,缓冲区中将不会遗留下回车换行符;
而对于 scanf()来说,使用 scanf()读走缓冲区中的字符串数据时,并不会将分隔符(空格、TAB 制表符、回车换行符等)读走将其丢弃,所以使用 scanf()读走缓冲区中的字符串数据之后,缓冲区中依然还存在用户输入的分隔符。
测试I:
int main(void)
{
char s1[100] = {0};
char s2[100] = {0};
scanf("%s", s1);
printf("s1: %s\n", s1);
scanf("%s", s2);
printf("s2: %s\n", s2);
exit(0);
}
当输入 123_456 回车时,输出结果如下(_表示空格):
代码中我们调用了两次 scanf(),而事实上我们只输入了一次,输入“123”之后输入空格、再输入“456”,然后按回车,由打印结果可知,字符串 s1 等于“123”,字符串 s2 等于“456”;当输入完成按回车之后,输入缓冲区中此时存在如下字符:
'1'、'2'、'3'、'空格'、'4'、'5'、'6'、'\n'
第一个 scanf()读取缓冲区时,将'1'、'2'、'3'读走,读走之后,它们将不存在于缓冲区中了,空格被 视为字符串分割符,分割符及后面的字符将不会读取(以%s 格式输入情况下)。
第二个 scanf()读取缓冲区时,'4'、'5'、'6'会被读走,分割符依然不读取。
再次执行测试程序:
当输入“123”回车,之后输出了“123”;之后需要再次输入,接着输入“456”回车,输出“456”。这里输入了两次字符串,原因在于第一次 scanf()读走“123”之后,缓冲区中只剩下回车换行字符,第二次scanf()不读取换行符,所以需要用户再次输入字符串。
测试II:
int main(void)
{
char s[100] = {0};
char c;
scanf("%s", s);
printf("s: %s\n", s);
scanf("%c", &c);
printf("c: %d\n", c);
exit(0);
}
执行结果:
这段代码也是调用了两次 scanf(),但只是输入了一次字符串,当第一个 scanf()读取之后,缓冲区
中只剩下回车换行符;从打印信息可以发现,第二次 scanf()读取时,把换行符也读取出来了(换行符'\n'对应的 ASCII 编码值等于 10),因为这里 scanf 用的是%c 格式,而不是%s,对于%c 读入时,空格、换行符、TAB 这些都是正常字符。
测试III:
int main(void)
{
char s1[100] = {0};
char s2[100] = {0};
scanf("%s", s1);
printf("s1: %s\n", s1);
gets(s2);
printf("s2: %s\n", s2);
exit(0);
}
执行结果:
这段代码先是调用了 scanf(),之后调用了 gets(),但只输入了一次字符串。scanf()读取之后,缓冲区中只剩下换行符,但是 gets()会将换行符读取出来并将其丢弃,所以说字符串便是一个空字符串。
再次执行测试程序:
字符串 s1 依然是“123”,scanf 读取完之后,缓冲区此时剩下如下字符串:
'空格'、'空格'、'4'、'5'、'6'、'\n'
gets()读取时将两个空格以及“456”、换行符全部读取出来,其中换行符会被丢弃、不作为字符串的组成字符,所以字符串 s2 前面就会存在两个空格。