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

C语言带3次尝试限制的用户名密码文件比对问题求助

修复你的C语言用户名密码验证程序

我来帮你搞定这个问题,你的代码主要在函数参数、文件读取逻辑、字符串比较和循环控制这几个地方出了问题,下面我先梳理问题点,再给出修复后的完整代码。

原代码的核心问题

  • 函数参数不匹配:identfilecreate和passverify的声明与定义参数不一致,比如identfilecreate声明要求传入char数组,但定义里没有参数,这会导致编译错误或未定义行为。
  • 文件读取重复且指针混乱:passverify每次调用都尝试从全局文件指针fpr读取,但第一次读完后指针已经到文件末尾,后续调用读不到任何内容;而且没必要每次验证都读文件,应该一次性加载所有用户信息。
  • 字符串比较逻辑错误:你读完文件后用line[i](此时i是总行数,已经超出数组索引范围)去和用户输入比较,正确的做法是遍历所有已加载的用户行逐个匹配。
  • 循环控制逻辑错误:main里的for循环不管验证成功与否都会执行3次,而且if ((i = 2))是赋值操作不是判断,完全起不到“3次失败后结束”的作用。
  • 全局变量滥用:全局文件指针容易引发意外问题,比如指针位置混乱,不如提前加载用户信息到数组中。

修复后的完整代码

#define LSIZ 128
#define RSIZ 10
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 全局存储用户信息数组,提前加载所有用户数据
char user_records[RSIZ][LSIZ];
int total_users = 0;

// 创建用户文件并加载所有用户信息到数组
void identfilecreate() {
    FILE *fpw = fopen("ident.txt", "w");
    if (!fpw) {
        perror("Failed to create file");
        exit(EXIT_FAILURE);
    }
    // 写入预设用户和密码,用制表符分隔
    fprintf(fpw, "Mark\t12345\nHannah\t23456\nJohn\t34567\nSammy\t45678\nDom\t56789\nOlivia\t67890\n");
    fclose(fpw);

    FILE *fpr = fopen("ident.txt", "r");
    if (!fpr) {
        perror("Failed to open file");
        exit(EXIT_FAILURE);
    }
    // 读取所有用户信息到全局数组,同时去掉换行符
    while (fgets(user_records[total_users], LSIZ, fpr) && total_users < RSIZ) {
        // 替换换行符为字符串结束符
        size_t len = strlen(user_records[total_users]);
        if (len > 0 && user_records[total_users][len - 1] == '\n') {
            user_records[total_users][len - 1] = '\0';
        }
        total_users++;
    }
    fclose(fpr);
}

// 验证用户输入,返回1表示验证成功,0表示失败
int passverify() {
    char user[LSIZ], pin[LSIZ], user_input[LSIZ];
    printf("Please enter your username: ");
    scanf("%s", user);
    printf("Please enter your pin: ");
    scanf("%s", pin);

    // 拼接用户名和密码,和文件中的格式保持一致(制表符分隔)
    snprintf(user_input, sizeof(user_input), "%s\t%s", user, pin);

    // 遍历所有用户记录,寻找匹配项
    for (int i = 0; i < total_users; i++) {
        if (strcmp(user_input, user_records[i]) == 0) {
            printf("You entered the correct username and password.\n");
            return 1; // 验证成功,返回1
        }
    }

    printf("You have entered the wrong username and password.\n");
    return 0; // 验证失败,返回0
}

int main() {
    // 初始化用户文件并加载数据
    identfilecreate();

    int attempts = 3;
    for (int i = 0; i < attempts; i++) {
        if (passverify() == 1) {
            // 验证成功,直接退出循环
            return 0;
        }
        // 提示剩余次数,注意最后一次失败后不需要提示
        if (i < attempts - 1) {
            printf("You have %d more tries\n", attempts - i - 1);
        }
    }

    // 3次失败后结束程序
    printf("The program will now end\n");
    return 0;
}

关键修改说明

  1. 全局用户数组:提前把所有用户信息加载到user_records数组中,后续验证直接用数组数据,避免重复读取文件,也解决了文件指针混乱的问题。
  2. 函数参数修正:统一了函数的声明和定义,identfilecreate改为无参数的void函数(因为不需要返回值,也不需要传入参数),passverify返回int类型表示验证结果。
  3. 字符串比较逻辑:用snprintf更安全地拼接用户输入(避免strcat可能的缓冲区溢出),然后遍历所有用户记录逐个比较,找到匹配项就立即返回成功。
  4. 循环控制优化:main函数中根据passverify的返回值决定是否终止循环,验证成功直接退出程序;失败后提示剩余次数,3次失败后才结束程序。
  5. 错误处理:添加了文件打开失败的错误提示,用perror打印具体错误信息,方便调试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:43:57