为什么它不调用 fgets?
Why won't it call fgets?
代码的目的是查看字符串是如何存储的(是否以 \n
或 [=14=]
结尾)。
void print(char*);
int main(void) {
//fscanf block
char *ss;
ss = malloc(sizeof(char)*100);
printf("String for fscanf: ");
fscanf(stdin, "%s", ss);
printf("For fscanf:\n");
print(ss);
//fgets block
char *gs;
gs = malloc(sizeof(char)*100);
printf("String for fgets: ");
fgets(gs, 10, stdin);
printf("For fgets:\n");
print(gs);
free(ss);
free(gs);
}
void print(char* str) {
int done = 0;
for (int i=0; i<100; i++){
if (done == 3) {
break;
}
if (str[i] == '[=10=]') {
printf("Zero: %d\n", i);
done++;
}
if (str[i] == '\n') {
printf("Return: %d\n", i);
done++;
}
}
}
但是由于某些原因,当我首先放置 fscanf 块时,它不会停止并请求 fgets 字符串,它只是跳过并输出:
String for fscanf: Hello
For fscanf:
Zero: 5
Zero: 6
String for fgets: For fgets:
Return: 0
Zero: 1
但是当我首先放置 fgets 块时它工作正常:
String for fgets: Hello
For fgets:
Return: 5
Zero: 6
String for fscanf: Hello
For fscanf:
Zero: 5
Zero: 6
为什么会出现这种情况?
scanf
和 fscanf
有很多注意事项 they get their own page in the C FAQ. Your particular problem of mixing fscanf and fgets is covered by 12.18a.
简而言之,您输入了 Hello\n
。 fscanf(stdin, "%s", ss)
正在读取字符串 Hello
,但不是换行符。那还在stdin
。 fgets
然后读取换行符并停止。调试这些东西时,最好在调试输出周围加上引号,这样您就可以看到这些东西。 printf("'%s'", gs);
一般来说,不要混用 fscanf
和 fgets
。坚持一个或另一个。通常避免 scanf
和 fscanf
读取和解析行,将读取和解析混为一谈会导致很多问题。相反,使用 fgets
读取整行并使用 sscanf
解析它。
它没有按预期工作,因为当您执行 fscanf(stdin, "%s", ss);
并按下 ENTER
时,它会将 ENTER
留在第二个缓冲区中。请注意 ENTER
是一个有效字符。因此它将读取 \n
作为第二个输入,而不会等待 fgets(gs, 10, stdin);
。为此,您需要在
之后清除 stdin
缓冲区
fscanf(stdin, "%s", ss);
完成它的一种方法是使用 getchar()
。例如
//fscanf block
getchar();/* help to clear the stdin buffer */
//fgets block
另请阅读此处为什么不应该使用 scanf()
以及应该使用什么来代替 scanf()
http://c-faq.com/stdio/scanfprobs.html
代码的目的是查看字符串是如何存储的(是否以 \n
或 [=14=]
结尾)。
void print(char*);
int main(void) {
//fscanf block
char *ss;
ss = malloc(sizeof(char)*100);
printf("String for fscanf: ");
fscanf(stdin, "%s", ss);
printf("For fscanf:\n");
print(ss);
//fgets block
char *gs;
gs = malloc(sizeof(char)*100);
printf("String for fgets: ");
fgets(gs, 10, stdin);
printf("For fgets:\n");
print(gs);
free(ss);
free(gs);
}
void print(char* str) {
int done = 0;
for (int i=0; i<100; i++){
if (done == 3) {
break;
}
if (str[i] == '[=10=]') {
printf("Zero: %d\n", i);
done++;
}
if (str[i] == '\n') {
printf("Return: %d\n", i);
done++;
}
}
}
但是由于某些原因,当我首先放置 fscanf 块时,它不会停止并请求 fgets 字符串,它只是跳过并输出:
String for fscanf: Hello
For fscanf:
Zero: 5
Zero: 6
String for fgets: For fgets:
Return: 0
Zero: 1
但是当我首先放置 fgets 块时它工作正常:
String for fgets: Hello
For fgets:
Return: 5
Zero: 6
String for fscanf: Hello
For fscanf:
Zero: 5
Zero: 6
为什么会出现这种情况?
scanf
和 fscanf
有很多注意事项 they get their own page in the C FAQ. Your particular problem of mixing fscanf and fgets is covered by 12.18a.
简而言之,您输入了 Hello\n
。 fscanf(stdin, "%s", ss)
正在读取字符串 Hello
,但不是换行符。那还在stdin
。 fgets
然后读取换行符并停止。调试这些东西时,最好在调试输出周围加上引号,这样您就可以看到这些东西。 printf("'%s'", gs);
一般来说,不要混用 fscanf
和 fgets
。坚持一个或另一个。通常避免 scanf
和 fscanf
读取和解析行,将读取和解析混为一谈会导致很多问题。相反,使用 fgets
读取整行并使用 sscanf
解析它。
它没有按预期工作,因为当您执行 fscanf(stdin, "%s", ss);
并按下 ENTER
时,它会将 ENTER
留在第二个缓冲区中。请注意 ENTER
是一个有效字符。因此它将读取 \n
作为第二个输入,而不会等待 fgets(gs, 10, stdin);
。为此,您需要在
stdin
缓冲区
fscanf(stdin, "%s", ss);
完成它的一种方法是使用 getchar()
。例如
//fscanf block
getchar();/* help to clear the stdin buffer */
//fgets block
另请阅读此处为什么不应该使用 scanf()
以及应该使用什么来代替 scanf()
http://c-faq.com/stdio/scanfprobs.html