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

C语言for循环、strcmp比对及文件读取功能异常问题求助

C身份验证代码修复方案

核心错误点

  • 缓冲区溢出:name数组仅分配5字节,无法容纳最长5位的用户名、空格、5位PIN码及结束符,拼接字符串时内存越界,结果不可预期
  • 文件操作顺序错误:先执行文件读取操作,再判断文件指针是否为空,文件打开失败时会直接触发崩溃;仅读取了文件第一行内容,没有遍历所有账户行;在循环内提前关闭文件,后续操作的是野指针
  • 首字符丢失:调用getc(file)吃掉了第一行的第一个字符,导致第一行账户内容残缺,永远匹配失败
  • 换行符未处理:fgets读取的行末尾自带换行符,和用户输入拼接的无换行字符串比对时永远不相等
  • for循环逻辑错误:循环条件写为i=3(赋值语句永远为真),导致死循环,无法实现3次尝试后终止的逻辑
  • 匹配逻辑残缺:仅与单次读取的一行内容比对,没有遍历所有账户信息,且匹配成功/失败后没有正确的分支跳转逻辑

修复后代码

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

#define MAX_TRY 3
#define MAX_NAME 16
#define MAX_PIN 8
#define MAX_LINE 32

int main()
{
    char input[MAX_LINE];
    char name[MAX_NAME], pin[MAX_PIN];
    char line_buf[MAX_LINE];
    FILE *file = NULL;
    int try_cnt = 0;
    int matched = 0;

    // 先判断文件是否打开成功
    file = fopen("ident.txt", "r");
    if (file == NULL) {
        printf("Error: could not open ident.txt\n");
        return 1;
    }

    // 最多允许3次尝试
    for (try_cnt = 0; try_cnt < MAX_TRY; try_cnt++) {
        printf("\n\tEnter your name: ");
        scanf("%s", name);
        printf("\n\tEnter your pin number: ");
        scanf("%s", pin);
        // 拼接用户输入,避免缓冲区溢出
        snprintf(input, sizeof(input), "%s %s", name, pin);
        printf("\n Entry: %s \n", input);

        // 重置文件指针到开头,遍历所有行比对
        rewind(file);
        matched = 0;
        while (fgets(line_buf, sizeof(line_buf), file) != NULL) {
            // 去掉fgets读取的末尾换行符
            line_buf[strcspn(line_buf, "\n")] = '\0';
            if (strcmp(line_buf, input) == 0) {
                matched = 1;
                break;
            }
        }

        if (matched) {
            printf("It's a Match\n");
            break;
        } else {
            if (try_cnt == MAX_TRY - 1) {
                printf("3 attempts failed, access denied\n");
            } else {
                printf("Invalid Entry. Try Again. \n");
            }
        }
    }

    fclose(file);
    return 0;
}

关键修改说明

  • 扩大了所有字符串缓冲区的大小,使用snprintf拼接用户输入避免溢出
  • 调整文件操作顺序,打开后先判断是否为空,使用rewind每次比对前重置文件指针,遍历所有账户行
  • 去掉了多余的getc调用,避免首字符丢失
  • 用strcspn去除fgets读取的换行符,保证比对逻辑正确
  • 修正for循环条件为try_cnt < MAX_TRY,实现3次尝试后自动终止
  • 增加匹配标志位,匹配成功直接退出,失败则计数累计直到3次

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 18:36:02