[英]Scanf clarification in c language
是否可以读取包含空格的整个字符串,例如scanf()
gets()
函数?
我可以使用gets()
函数来做到这一点。
char s[30];
gets(s);
这将读取一行字符。 这可以在scanf()
吗?
您可以使用scanf()
读取一行,包括空格,但是这个函数很微妙,使用它很容易出错。 使用%[^\\n]
转换说明符,您可以告诉scanf()
匹配字符以形成字符串,不包括'\\n'
字符。 如果这样做,则应指定最大字段宽度。 此宽度指定要匹配的最大字符数,因此您必须为'\\0'
终止符留出空间。
输入流中的第一个字符可能是'\\n'
。 在这种情况下, scanf()
将返回值0
,因为在遇到换行符之前没有匹配项。 但是, s
不会存储任何内容,因此您可能有未定义的行为。 为避免这种情况,您可以首先使用%*[\\n]
转换说明符调用scanf()
,丢弃任何前导'\\n'
字符。
字符串被读取后,输入流中会有额外的字符。 至少存在一个'\\n'
,如果用户输入的字符超过指定的最大字段宽度,则可能还有更多字符。 然后您可能想要丢弃这些额外的字符,以便它们不会干扰进一步的输入。 下面的代码包含一个循环来执行此操作。
第一次调用scanf()
将消耗输入流中的所有换行符,直到遇到非换行符。 虽然我认为对scanf()
的第二次调用应该总是成功的,但始终检查scanf()
的返回值(这是成功分配的次数scanf()
是一种很好的做法。 我已将此值存储在result
,并在打印字符串之前检查它。 如果scanf()
返回意外结果,则会打印错误消息。
使用fgets()
读取整行会更好也更容易。 您必须记住fgets()
保留了尾随换行符,因此您可能希望将其删除。 也有可能用户输入的字符多于缓冲区存储的字符数,而将剩余的字符留在输入流中。 在提示更多输入之前,您可能希望删除这些额外的字符。
同样,您应该检查fgets()
的返回值; 此函数返回指向存储缓冲区第一个元素的指针,或在发生错误时返回NULL
指针。 下面的代码替换字符串中的任何尾随换行符,丢弃输入流中的额外字符,并仅在调用fgets()
成功时才打印字符串。 否则,将打印错误消息。
#include <stdio.h>
int main(void)
{
char s[30];
int result;
printf("Please enter a line of input:\n");
scanf("%*[\n]"); // throw away leading '\n' if present
result = scanf("%29[^\n]", s); // match up to 29 characters, excluding '\n'
/* Clear extra characters from input stream */
int c;
while ((c = getchar()) != '\n' && c != EOF)
continue; // discard extra characters
if (result == 1) {
puts(s);
} else {
fprintf(stderr, "EOF reached or error in scanf()\n");
}
printf("Please enter a line of input:\n");
char *ps = fgets(s, 30, stdin); // keeps '\n' character
if (ps) {
while (*ps && *ps != '\n') {
++ps;
}
if (*ps) { // replace '\n' with '\0'
*ps = '\0';
} else {
while ((c = getchar()) != '\n' && c != EOF)
continue; // discard extra characters
}
puts(s);
} else {
fprintf(stderr, "EOF reached or error in fgets()\n");
}
return 0;
}
请注意,这两种获取输入行的方法并不完全等效。 此处所写的scanf()
方法不接受空行(即仅由'\\n'
字符组成的行),但接受由其他空白字符组成的行。 fscanf()
方法将接受一个空行作为输入。
此外,如果忽略前导空格字符是可以接受的,那么遵循 Jonathan Leffler 在评论中给出的建议只使用一次scanf()
调用会更简单:
result = scanf(" %29[^\n]", s);
这将忽略前导空白字符,包括换行符。
不要使用scanf()
或gets()
函数 — 使用fgets()
代替。 但是对于上面的问题,请找到答案。
int main() {
char a[30];
scanf ("%29[^\n]%*c", name);
printf("%s\n", a);
return 0;
}
它也强烈推荐,就像我在开始时所说的那样使用fgets()
代替。 我们显然不理解奇怪的要求。 我会使用fgets()
来读取字符。
fgets(a, size(a), stdin);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.