C-跳过用户输入?

C-跳过用户输入?,c,switch-statement,printf,flush,C,Switch Statement,Printf,Flush,我想要一个菜单,你可以从中选择一些动作 问题是,当我们选择一个并按下“return”键时,应该是下一步的用户输入命令被跳过。为什么呢 代码是: #include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { int choice; do { printf("Menu\n\n"); printf("1. Do this\n"); pr

我想要一个菜单,你可以从中选择一些动作

问题是,当我们选择一个并按下“return”键时,应该是下一步的用户输入命令被跳过。为什么呢

代码是:

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    int choice;

    do
    {
     printf("Menu\n\n");
     printf("1. Do this\n");
     printf("2. Do that\n");
     printf("3. Leave\n");
     scanf("%d",&choice);

     switch (choice)
     {
        case 1:
            do_this();
            break;
        case 2:
            // do_that();
            break;
     }

    } while (choice != 3);

    return(0);
}

int do_this()
{
    char name[31];

    printf("Please enter a name (within 30 char) : \n");
    gets(name); // I know using gets is bad but I'm just using it

    // fgets(name,31,stdin); // gives the same problem by the way.

    // Problem is : user input gets skiped to the next statement :
    printf("Something else \n");

    return(0);
}
#包括
#包括
int main(int argc,char*argv[])
{
智力选择;
做
{
printf(“菜单\n\n”);
printf(“1.这样做\n”);
printf(“2.这样做\n”);
printf(“3.离开\n”);
scanf(“%d”,选择(&C);
开关(选择)
{
案例1:
做这件事吗;
打破
案例2:
//做那件事吗;
打破
}
}while(选项!=3);
返回(0);
}
int do_this()
{
字符名[31];
printf(“请输入名称(30个字符以内):\n”);
gets(name);//我知道使用gets很糟糕,但我只是在使用它
//fgets(name,31,stdin);//顺便提一下,给出了同样的问题。
//问题是:用户输入被跳过到下一个语句:
printf(“其他东西”);
返回(0);
}
scanf()
留下一个新行,随后调用
gets()
会使用该新行

使用
getchar()
紧跟在
scanf()
之后,或使用循环读取和丢弃字符:

int c;
while((c= getchar()) != '\n' && c != EOF); 
我知道你评论过
get()
不好。但是你甚至不应该尝试使用它,即使它是一个玩具程序。它已从最新的C标准(C11)中完全删除,即使您正在为C89编程,也不应使用它(由于其缓冲区溢出漏洞)。使用
fgets()
,除了可能留下一个尾随的换行符外,其作用几乎相同

如果这是您的完整代码,那么您还需要一个原型或至少一个
do\u this()
的声明。隐式int规则也已从C标准中删除。那么加上

int do_this();
在源文件的顶部

scanf("%d",&choice);
这将在标准输入缓冲区
stdin
中保留换行符(
'\n'

调用
gets()
只会占用空白,不会将任何内容写入
name


为了防止这种情况,请在调用scanf后使用换行符,例如使用
getchar()
。如果您不在microsoft平台上,请不要使用
fflush(stdin)
,因为这是未定义的行为(在非MS平台上)。

您使用用户输入做什么?我认为问题在于
scanf
。这不是让换行符保留在
stdin
中吗?也许这就是跳过
fgets
的原因。但是,我通常不使用scanf,所以我不能肯定。你刚刚提到了这个问题。您可以按两个键进行
scanf
。该数字由
scanf
使用,而
\n
(回车)保留在
stdin
中。因此,
获取
/
fgets
会看到
\n
并使用它,因此不会等待进一步的输入。使用
scanf(“%d%*c”和&choice)修复它而不是
scanf(“%d”和&choice)
%*c
告诉
scanf
扫描并丢弃一个字符。你可以通过谷歌搜索标题找到它。在web和stackoverflow中都有大量的重复项。@CoolGuy您的解决方案有效!当然,我在谷歌上搜索了一下,但没有找到任何明确的答案:(如果我可以让用户选择
int
而不使用
scanf
,那么这一切都是不必要的,但这可能吗?@lapin我不这么认为,除非你想跳转,将其作为字符串并手动将其转换为int。这可能会起作用,因为所有十进制数字都是ascii格式的后续数字。你也可以做一个表单。)所有检查用户是否以这种方式输入了正确的输入。@lapin问题的原因不是
scanf()
本身,而是
scanf()
+
[f]get()
的组合。一般来说,最好不要将
scanf()
fgets()
混用,最好不要使用
scanf()
。一种更稳健的方法是使用fgets(),然后在线使用
sscanf()
。请注意,在Microsoft平台上,是定义的行为。AFAICS,您无条件地写了“使用
fflush(stdin)
是未定义的行为”——我在评论微软,
fflush(stdin)
已经定义(并且有用)行为,所以你的无条件语句太过笼统,因为它是无条件的,这尤其是一个问题,因为许多使用它的人都在一个定义了行为的环境中工作。这是对
fflush(stdin)实用程序的两种不同描述
。在C中,原型应该是
int do_this(void);
(或者更好的是,
static int do_this(void);
,因为函数不会从该文件外部调用-如果要从该文件外部调用,那么声明当然应该在头中)。这一点的意义在于
int do_this();
只是说“有一个函数返回一个
int
,但参数列表未定义-但它不是一个以省略号
作为最后一个参数的变量函数”它并没有说明函数不带参数,不像C++中的那样。谢谢大家的回答。这就是问题的原因。我使用了上面的SooGy建议的快速修复。@ LAPIN,本质上相当于添加<代码> GETCHARE();<代码>调用SCANFF()后调用,即Read <代码> %*C<(称为赋值抑制字符)读取并丢弃一个字符。只要您了解根本问题,就可以使用任何适合您需要的解决方案。