在 C 语言里,scanf
函数是一个常用的输入函数。不过呢,它在读取输入时会因为一些情况而停止录入,这可能会让输入缓冲区残留一些字符,进而影响后续的输入操作。 scanf
停止录入的情况以及相关注意事项。
1. 数组名作为地址传递给 scanf
在使用 scanf
读取字符串时,我们常常会用到字符数组。要注意啦,数组名本身就代表数组首元素的地址,所以在 scanf
里不需要再加取地址符 &
。
#include <stdio.h>
int main() {
char password[19] = {0};
// 这里 password 本身就是地址,无需加 &
scanf("%s", password);
printf("你输入的密码是:%s\n", password);
return 0;
}
2. 遇到空白字符停止读取
scanf
在读取 %s
格式的字符串时,会把空白字符(像空格、制表符 \t
、换行符 \n
等)当作字符串的结束标志。
#include <stdio.h>
int main() {
char str[20];
printf("请输入一个包含空格的字符串:");
scanf("%s", str);
// 输入 "hello world",scanf 遇到空格停止,str 只存 "hello"
printf("你输入的字符串是:%s\n", str);
return 0;
}
在这个例子中,当你输入 hello world
时,scanf
遇到空格就不再继续读取了,str
数组里只会存储 hello
,而 world
以及后面可能的内容会留在输入缓冲区中。
3. 达到指定的最大宽度停止读取
要是在格式控制字符串里指定了最大宽度,scanf
读取到指定宽度的字符后就会停止。
#include <stdio.h>
int main() {
char str[20];
printf("请输入一个字符串:");
// 指定最大宽度为 5
scanf("%5s", str);
// 输入 "abcdefg",scanf 只读前 5 个字符 "abcde"
printf("你输入的字符串是:%s\n", str);
return 0;
}
这里,如果你输入 abcdefg
,scanf
只会读取前 5 个字符 abcde
存到 str
数组中,剩下的字符 fg
会留在输入缓冲区。
4. 无法匹配格式控制字符串停止读取
如果输入的内容没办法和格式控制字符串匹配,scanf
也会停止读取。
#include <stdio.h>
int main() {
int num;
printf("请输入一个整数:");
scanf("%d", &num);
// 输入 "abc",无法转换为整数,scanf 停止
printf("你输入的整数是:%d\n", num);
return 0;
}
当你输入 abc
时,因为 abc
没办法转换成整数,scanf
就会停止读取,并且 abc
会留在输入缓冲区。要是后续还有输入操作,就可能会受到这些残留字符的影响。
5. 遇到文件结束符(EOF)停止读取
在某些情形下,当输入流到达文件结束符时,scanf
也会停止读取。在 Windows 系统中,按下 Ctrl + Z
会产生文件结束符;在 Unix/Linux 系统中,按下 Ctrl + D
会产生文件结束符。
#include <stdio.h>
int main() {
char ch;
printf("请输入字符,按 Ctrl+Z(Windows)或 Ctrl+D(Unix/Linux)结束输入:");
while ((ch = getchar()) != EOF) {
// 这里可以对输入的字符进行处理
}
printf("输入结束\n");
return 0;
}
在这个例子里,当你按下对应的组合键产生文件结束符时,scanf
或者 getchar
等输入函数就会停止读取。
6. 缓冲区残留字符影响后续输入
由于 scanf
存在上述这些停止录入的情况,可能会让输入缓冲区残留一些字符,从而影响后续的输入操作。
#include <stdio.h>
int main() {
char str[20];
int num;
printf("请输入一个字符串:");
scanf("%s", str);
// 这里可能残留换行符在缓冲区
printf("请输入一个整数:");
scanf("%d", &num);
printf("你输入的字符串是:%s,整数是:%d\n", str, num);
return 0;
}
在这个例子中,第一个 scanf
读取字符串后,输入缓冲区可能会残留换行符。当执行第二个 scanf
读取整数时,这个换行符可能会对输入造成影响。
7. 清理输入缓冲区
为了保证后续输入的准确性,在需要连续进行输入操作时,通常要清理输入缓冲区。
#include <stdio.h>
int main() {
char str[20];
int num;
printf("请输入一个字符串:");
scanf("%s", str);
// 清理输入缓冲区
while (getchar() != '\n');
printf("请输入一个整数:");
scanf("%d", &num);
printf("你输入的字符串是:%s,整数是:%d\n", str, num);
return 0;
}
这里使用 while (getchar() != '\n');
来清理输入缓冲区,把缓冲区里的字符一直读取到换行符为止。
8. scanf
的返回值
scanf
函数会返回成功匹配并赋值的输入项的数量。可以通过检查 scanf
的返回值来判断输入是否成功。
#include <stdio.h>
int main() {
int num;
int result = scanf("%d", &num);
if (result == 1) {
printf("成功输入一个整数:%d\n", num);
} else {
printf("输入失败,请输入一个有效的整数。\n");
}
return 0;
}
在这个例子中,如果 scanf
成功读取一个整数,它会返回 1;如果输入不匹配,返回值就不是 1。
9. 读取多个输入项
scanf
可以同时读取多个输入项,用空格分隔不同的格式控制符。
#include <stdio.h>
int main() {
int a, b;
printf("请输入两个整数,用空格分隔:");
scanf("%d %d", &a, &b);
printf("你输入的两个整数是:%d 和 %d\n", a, b);
return 0;
}
这里 scanf
会依次读取两个整数,分别赋值给 a
和 b
。
10. 格式控制字符串中的非格式字符
在格式控制字符串中可以包含非格式字符,输入时必须按原样输入这些字符。
#include <stdio.h>
int main() {
int day, month, year;
printf("请按 日/月/年 的格式输入日期:");
// 这里的 / 是非格式字符,输入时要原样输入
scanf("%d/%d/%d", &day, &month, &year);
printf("你输入的日期是:%d 年 %d 月 %d 日\n", year, month, day);
return 0;
}
在这个例子中,输入时必须按照 日/月/年
的格式,输入对应的数字和 /
字符。
11. 读取字符时的注意事项
在读取字符时,要特别注意输入缓冲区里的换行符等空白字符。
#include <stdio.h>
int main() {
char ch1, ch2;
printf("请输入第一个字符:");
scanf("%c", &ch1);
// 清理缓冲区的换行符
while (getchar() != '\n');
printf("请输入第二个字符:");
scanf("%c", &ch2);
printf("你输入的两个字符是:%c 和 %c\n", ch1, ch2);
return 0;
}
这里在读取第二个字符前,先清理了缓冲区的换行符,避免它被当作第二个字符读取。
12. 避免缓冲区溢出
在使用 scanf
读取字符串时,要确保数组有足够的空间,避免缓冲区溢出。
#include <stdio.h>
int main() {
// 定义一个长度为 10 的字符数组
char str[10];
printf("请输入一个字符串:");
// 限制输入长度为 9,留一个位置给字符串结束符 \0
scanf("%9s", str);
printf("你输入的字符串是:%s\n", str);
return 0;
}
在这个例子中,使用 %9s
限制输入的长度,避免输入的字符串超出数组的大小。
通过以上这些内容,相信你对 scanf
函数的输入结束标志和注意事项有了解。在实际编程中,要注意这些细节,才能让程序更加稳定和健壮。