在同一个程序中使用scanf和fgets?

时间:2011-04-05 03:29:11

标签: c scanf

我需要做以下事情:

int main(void) {
char a,b,cstring;

printf("please enter something");
scanf("%c %c",&a,&b);
prinf("thanks, now some more");
fgets(cstring,35,stdin);

}

问题是每当我从scanf输入第一个变量时,它都会跳到程序的末尾。我该如何做多个输入?

4 个答案:

答案 0 :(得分:7)

第一个问题是scanf()读取了两个字符,但后来没有读取换行符。

这意味着您的fgets()会读取换行符并完成。

你很幸运,你的程序没有崩溃。你告诉fgets()它正在获得一个包含35个字符的数组,但是你传递的是字符(而不是字符的地址,而不是传递数组)。这也告诉我们你不是包括#include <stdio.h>(你不能根据C标准可靠地使用scanf()而没有范围内scanf()的原型,而你不是编译时启用了足够的警告,或者没有足够重视编译器告诉你的内容。

您应该收到编译器警告。例如,GCC 4.6.0说:

/usr/bin/gcc -g -I/Users/jleffler/inc -std=c99 -Wall -Wextra -Wmissing-prototypes \
     -Wstrict-prototypes -Wold-style-definition xxx.c
xxx.c: In function ‘main’:
xxx.c:7: warning: implicit declaration of function ‘prinf’
xxx.c:8: warning: passing argument 1 of ‘fgets’ makes pointer from integer without a cast

并且,在我尝试链接之前,我甚至没有注意到prinf()printf()的拼写错误,并且编辑器通过说“不知道是什么{来揉捏我的鼻子” {1}}是!“。

如果你的编译器至少没有给出第二个警告,那就给自己一个更好的编译器。


注释:

  

如何阻止它在阅读换行符之后?

问题不是阻止prinf()阅读换行符;问题实际上是如何让它读取它,以便scanf()在下一行输入中获得清晰的运行。它实际上是非常棘手的 - 我很少使用fgets()的原因之一(但我经常使用scanf())。这可以完成简单输入的工作:

sscanf()

#include <stdio.h> int main(void) { char a,b,cstring[35]; printf("please enter something"); scanf("%c %c%*c", &a, &b); printf("thanks, now some more"); fgets(cstring, 35, stdin); printf("OK: I got %c and %c and <<%s>>\n", a, b, cstring); return 0; } 读取一个额外的字符(换行符)而不将其分配到任何地方(这是因为%*c)。但是,如果第二个非空白后有多个字符,则无济于事。我可能会写一个循环来读取换行符:

*

请注意,#include <stdio.h> int main(void) { char a,b,cstring[35]; int c; printf("please enter something"); scanf("%c %c", &a, &b); while ((c = getchar()) != EOF && c != '\n') ; printf("thanks, now some more"); fgets(cstring, 35, stdin); printf("OK: I got %c and %c and <<%s>>\n", a, b, cstring); return 0; } 会返回getchar()而不是int。这可靠地丢弃第一行输入上的所有内容。它还显示了如何回显您所读取的内容 - 这是调试的一个重要部分。

答案 1 :(得分:1)

这是未定义的行为。您的cstring变量,无论其名称是什么,都是一个字符,并且您尝试将最多35个字符读取为其当前值指向的字符。换句话说,cstring中的当前字符将转换为指针,它将尝试在那里写入您的输入。这将是一个介于0到255之间的内存位置(最有可能)。

这就是导致细分违规的原因。从这样的事情开始:

#include <stdio.h>
int main(void) {
    char a,b,cstring[99];

    printf("please enter something");
    scanf("%c %c",&a,&b);
    printf("thanks, now some more");
    fgets(cstring,35,stdin);

    return 0;
}

或者,可能更好:

#include <stdio.h>
int main(void) {
    char a,b,cstring[99];

    printf("please enter something");
    fgets(cstring,35,stdin);
    sscanf(cstring,"%c %c",&a,&b);
    printf("thanks, now some more");
    fgets(cstring,35,stdin);

    return 0;
}

或者,如果您想要一个更强大的用户输入解决方案,请参阅here。这是一种久经考验的方法,具有非常好的错误检查功能。

答案 2 :(得分:0)

问题是当流程到达fgets()时,此API首先查看stdin以获取输入,并在那里找到一个迷路'\ n'。至于fgets(),它表示此API在遇到EOF或'\ n'时返回,因为fgets()从stdin获得'\ n',所以它执行时无需等待用户输入内容,因为API返回条件满足。< / p>

问题的解决方法是使用getchar();在scanf之后,忽略scanf()留下的额外字符。 e.g:

scanf("%lf",&e);
getchar();
fgets(t,200,stdin);

其他解决方案可以是使用带有fgets的sscanf。 e.g:

#include <stdio.h>
int main() {
int j;char t[200];
fgets(t,200,stdin);
sscanf(t,"%d",&j);
}

答案 3 :(得分:-1)

使用scanf后可以使用fflush(stdin)来解决问题