You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言if语句下输入被跳过问题求助(无if时功能正常)

问题:scanf读取整数后fgets跳过输入的解决办法

我写了一个C程序,让用户选择1(创建文件)或2(追加文件),但运行时if (opt == 1)分支里,程序会跳过文件名的输入步骤。

期望输出:

Enter a file name: (input)
Enter file contents: (input)

实际输出:

Enter a file name: Enter file contents: (input)

原代码:

#include <stdio.h>

int main(void) {

    char fname[20];
    char fcontents[250];
    int opt;

    printf("Make a file(1),Append a file(2)");
    scanf("%d", &opt);

    if (opt == 1)
    {
        printf("Enter a file name: ");
        fgets(fname, 20, stdin);
        printf("Enter file contents: ");
        fgets(fcontents, 250, stdin);
        FILE* fpointer = fopen(fname, "w");
        fprintf(fpointer, "%s", fcontents);
        fclose(fpointer);
        printf("FILE: %s successfully created", fname);
    }
    else if (opt == 2) 
    {
        printf("Enter a file name: ");
        fgets(fname, 20, stdin);
        printf("Enter file appends: ");
        fgets(fcontents, 250, stdin);
        FILE* fpointer = fopen(fname, "a");
        fprintf(fpointer, "%s", fcontents);
        fclose(fpointer);
        printf("FILE: %s successfully created", fname);
    }
}

问题原因

问题出在scanf("%d", &opt);这行:当你输入数字后按回车,输入缓冲区里会残留一个换行符,scanf只读取了数字,没处理这个换行符。后续调用fgets时,它会直接读取这个换行符,误以为已经完成了文件名的输入,于是跳过了用户手动输入的步骤。

另外还有个隐藏问题:fgets会把换行符也读进字符串里,比如输入test.txt回车后,fname里会是test.txt\n,这会导致fopen找不到目标文件。

解决方案

方法1:用getchar清除缓冲区换行符

在scanf之后加一行getchar(),吃掉残留的换行符:

printf("Make a file(1),Append a file(2): ");
scanf("%d", &opt);
getchar(); // 清除输入缓冲区的换行符

方法2:在scanf格式串中处理空白字符

修改scanf的格式,让它自动忽略换行、空格等空白字符:

// 用\n跳过换行
scanf("%d\n", &opt);
// 或者用空格跳过所有空白字符
scanf("%d ", &opt);

方法3:统一用fgets读取输入再转整数

避免混用scanf和fgets,先读取整行输入,再用sscanf转成整数:

char opt_str[10];
printf("Make a file(1),Append a file(2): ");
fgets(opt_str, 10, stdin);
sscanf(opt_str, "%d", &opt);

附加处理:去掉fgets读取的换行符

不管用哪种方法,都建议给fgets读取的字符串去掉换行符,避免文件打开失败:

// 需要包含string.h头文件
fname[strcspn(fname, "\n")] = '\0';

完整修改后的代码(以方法1为例)

#include <stdio.h>
#include <string.h> // 用于strcspn函数

int main(void) {

    char fname[20];
    char fcontents[250];
    int opt;

    printf("Make a file(1),Append a file(2): ");
    scanf("%d", &opt);
    getchar(); // 清除缓冲区的换行符

    if (opt == 1)
    {
        printf("Enter a file name: ");
        fgets(fname, 20, stdin);
        fname[strcspn(fname, "\n")] = '\0'; // 去掉换行符
        printf("Enter file contents: ");
        fgets(fcontents, 250, stdin);
        
        FILE* fpointer = fopen(fname, "w");
        if (fpointer != NULL) { // 检查文件是否成功打开
            fprintf(fpointer, "%s", fcontents);
            fclose(fpointer);
            printf("FILE: %s successfully created\n", fname);
        } else {
            printf("Failed to open file %s\n", fname);
        }
    }
    else if (opt == 2) 
    {
        printf("Enter a file name: ");
        fgets(fname, 20, stdin);
        fname[strcspn(fname, "\n")] = '\0'; // 去掉换行符
        printf("Enter file appends: ");
        fgets(fcontents, 250, stdin);
        
        FILE* fpointer = fopen(fname, "a");
        if (fpointer != NULL) { // 检查文件是否成功打开
            fprintf(fpointer, "%s", fcontents);
            fclose(fpointer);
            printf("FILE: %s successfully appended\n", fname);
        } else {
            printf("Failed to open file %s\n", fname);
        }
    } else {
        printf("Invalid option\n");
    }
    return 0;
}

内容的提问来源于stack exchange,提问作者user18326065

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 02:25:35