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

C语言结构体输入异常:使用fgets()仍无法获取首个输入

解决C语言结构体输入时fgets跳过首个字段的问题

这个问题我太熟了——你用scanf输入书籍数量后,第一个fgets直接跳过Titulli的输入,根本不给你输入的机会,直接跳到Autori。本质原因是**scanf("%d", &n)读取完整数后,会把你按下的回车键(换行符\n)留在标准输入缓冲区里**。接下来的fgets一看到缓冲区里的换行符,就误以为你输入了空行,直接把这个换行符读进去了,所以看起来像是跳过了第一个输入项。

快速解决方法

最直接的修复就是在scanf读取数字后,把残留的换行符吃掉,有几种简单的方式:

  1. 用getchar()吃掉换行
    在scanf("%d", &n);之后加一行:
getchar(); // 把scanf留下的换行符从缓冲区里清掉

这种方法适合你当前的场景,只要用户输入数字后直接回车,就能完美解决。

  1. 用scanf的格式字符串自动处理
    把读取数字的scanf改成这样:
scanf("%d%*c", &n); // %*c表示读取一个字符但不保存,专门用来吃掉换行

%*c会自动读取紧跟在数字后的换行符,不用额外调用函数。

  1. 彻底避免scanf和fgets混用(更推荐)
    如果你不想再遇到这类缓冲区问题,可以用fgets读取整行输入,再用sscanf从中提取数字,完全避开scanf的坑:
char input_buf[20];
printf("\n\tShkruani numrine librave qe doni te shtoni: ");
fgets(input_buf, sizeof(input_buf), stdin);
sscanf(input_buf, "%d", &n);

这样输入缓冲区里不会残留任何多余字符,后续的fgets都能正常工作。

额外的小修复建议

除了核心问题,你的代码还有几个小细节可以优化:

  • fgets会读取换行符:fgets会把用户输入的回车也存入字符串,后续用puts输出时会多一个空行。可以用strcspn去掉换行符:
    fgets(libra[nr].titulli, 50, stdin);
    libra[nr].titulli[strcspn(libra[nr].titulli, "\n")] = '\0'; // 替换换行符为字符串结束符
    
  • kerko_titulli函数的循环错误:你写的while (fread(...) == 1);后面多了个分号,这会导致循环只是不断读取文件内容,完全不执行后面的判断逻辑。应该把分号去掉,把判断逻辑放到循环体里:
    nr = 0;
    while (fread( &libra[nr], sizeof(struct liber), 1, flib) == 1) {
        if (strcmp(v_autori, libra[nr].autori) == 0) {
            // 输出书籍信息的代码
        }
        nr++;
    }
    
  • main函数的输入类型问题:你用char z;但用scanf("%d", &z)读取整数,这会导致类型不匹配。如果要支持输入数字选项和e退出,应该改成:
    char z;
    do {
        menu();
        scanf(" %c", &z); // 前面的空格用来跳过空白字符(比如换行)
        if (z == '1') shtoliber();
        else if (z == '2') kerko_titulli();
    } while (z != 'e' && z != 'E' && z != 27);
    

修改后的核心函数示例

这里给你改好的shtoliber函数,解决了输入问题还处理了换行符:

void shtoliber() {
    int i, n = 0;
    FILE * flib;
    flib = fopen("libra.dat", "wb");
    if (flib == NULL) {
        printf("\nGabim ne hapjen e file!!");
        getch();
        exit(1);
    }
    printf("\n\tShkruani numrine librave qe doni te shtoni: ");
    scanf("%d", &n);
    getchar(); // 清理输入缓冲区的换行符
    
    for (i = 0; i < n; i++) {
        printf("\nTitulli: ");
        fgets(libra[nr].titulli, 50, stdin);
        libra[nr].titulli[strcspn(libra[nr].titulli, "\n")] = '\0';
        
        printf("\nAutori: ");
        fgets(libra[nr].autori, 20, stdin);
        libra[nr].autori[strcspn(libra[nr].autori, "\n")] = '\0';
        
        printf("\nKategoria: ");
        fgets(libra[nr].kategoria, 20, stdin);
        libra[nr].kategoria[strcspn(libra[nr].kategoria, "\n")] = '\0';
        
        printf("\nID: ");
        fgets(libra[nr].id, 10, stdin);
        libra[nr].id[strcspn(libra[nr].id, "\n")] = '\0';
        
        printf("\nKopje: ");
        scanf("%d", &libra[nr].kopje);
        getchar(); // 清理输入Kopje后的换行符,避免下一次循环出问题
        
        printf("\n*****************\n");
        fwrite( &libra[nr], sizeof(struct liber), 1, flib);
        printf("\nLibri u regjistrua.\n\v");
        nr++;
    }
    fclose(flib);
}

内容的提问来源于stack exchange,提问作者s.dokaj

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:07:09