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

C语言读取txt文件字符串实现登录校验异常排查

C语言登录校验功能异常修复

核心问题成因

现有代码存在6处逻辑错误,直接导致校验失败、输出乱码:

  • 缓冲区长度定义错误:使用strlen(usuario)/strlen(contrasenia)作为读取缓冲区长度与fgets的读取长度参数,既没有为字符串结束符\0预留空间,也没有考虑fgets会读取行尾换行符的特性,直接造成缓冲区溢出、字符串截断,你看到的单字符'd'、乱码拼接内容就是溢出的典型表现。
  • 文件遍历逻辑完全失效:在遍历文件的while(!feof)循环内第一行就执行fseek(docInicioSesion, 0, SEEK_SET)重置文件指针到开头,循环会无限执行,永远无法逐行遍历所有账号密码对,最终只会读到截断的异常内容。
  • 匹配判断逻辑写反:strcmp函数在两个字符串完全相等时返回值为0,现有判断条件strcmp(usuario, stringUser) && strcmp(contrasenia, stringPassword)的含义是「用户名和密码都不匹配时判定为登录成功」,逻辑完全颠倒。
  • 换行符未做清理:fgets读取文件行时会将行尾的换行符\n存入字符串,而scanf读取的用户输入不带换行符,即便账号密码完全正确,也会因为多了换行符导致比对失败。
  • 循环条件错误:do-while循环判断用了||逻辑,即便是登录成功(ingreso=1),只要尝试次数小于3就会继续循环,无法正常跳出登录流程。
  • 环境兼容问题:Replit运行环境为Linux,原代码用的system("cls")(Windows清屏)、system("pause")(Windows暂停)、system("exit")命令均无法正常执行。

修复后可直接运行的代码

1. iniciarSesion.h

#define maxIntentos 3
void iniciarSesion();

2. iniciarSesion.c

适配标准C语法,兼容Replit Linux环境:

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

// 辅助函数:去除fgets读取到的行尾换行符
void trimNewline(char* str) {
    int len = strlen(str);
    if (len > 0 && str[len-1] == '\n') {
        str[len-1] = '\0';
    }
}

void iniciarSesion() {
    FILE *docInicioSesion;
    // 缓冲区开固定足够长度,避免溢出
    char usuario[40], contrasenia[30];
    char fileUser[40], filePass[30];
    int tries = 0, ingreso = 0;

    docInicioSesion = fopen("saveData.txt", "r");
    if (docInicioSesion == NULL) {
        printf("\nError al abrir el archivo\n");
        return;
    }

    do {
        // 兼容Linux/Windows清屏
        #ifdef _WIN32
        system("cls");
        #else
        system("clear");
        #endif

        printf("\n\t\t INICIO DE SESION\n\n");
        printf("Usuario: ");
        scanf("%39s", usuario); // 限制输入长度避免溢出
        printf("Contrasena: ");
        scanf("%29s", contrasenia);
        // 清空输入缓冲区残留的换行符
        while(getchar() != '\n');

        // 每次校验前把文件指针重置到开头
        fseek(docInicioSesion, 0, SEEK_SET);
        ingreso = 0;

        // 逐组读取用户名+密码,直到文件末尾
        while (fgets(fileUser, sizeof(fileUser), docInicioSesion) != NULL) {
            trimNewline(fileUser);
            // 用户名读完读对应密码,判断是否读到文件末尾
            if (fgets(filePass, sizeof(filePass), docInicioSesion) == NULL) {
                break;
            }
            trimNewline(filePass);

            // 两个字符串都相等才判定匹配成功
            if (strcmp(usuario, fileUser) == 0 && strcmp(contrasenia, filePass) == 0) {
                ingreso = 1;
                break;
            }
        }

        if (ingreso == 1) {
            #ifdef _WIN32
            system("cls");
            #else
            system("clear");
            #endif
            printf("\nAcceso Concedido!\n");
            printf("Bienvenido/a %s!\n", usuario);
            printf("Presione Enter para continuar...");
            getchar();
            break;
        } else {
            printf("Acceso denegado\nLa clave y/o usuario son incorrectos...\n");
            tries++;
            if (tries < maxIntentos) {
                printf("Intentos restantes: %d\nPresione Enter para continuar...", maxIntentos - tries);
                getchar();
            }
        }
    } while(tries < maxIntentos && ingreso != 1);

    if (tries == maxIntentos) {
        printf("Ha sobrepasado el limite maximo de intentos.\n");
        printf("Presione Enter para salir...");
        getchar();
        fclose(docInicioSesion);
        exit(1);
    }

    fclose(docInicioSesion);
}

修复说明

  • 所有缓冲区使用固定长度,scanf/fgets均限制最大读取长度,从根源避免缓冲区溢出
  • 修正文件遍历逻辑:每次用户输入后重置文件指针,逐组读取用户名、密码对,读到文件末尾自动结束
  • 新增换行符清理函数,统一处理文件读入内容的行尾换行,保证比对逻辑一致
  • 修正strcmp判断条件,仅当用户名、密码完全匹配时判定登录成功
  • 增加跨平台适配,自动识别Windows/Linux环境调用对应清屏命令,用标准输入函数实现暂停逻辑,兼容Replit环境
  • 修正循环判断逻辑,登录成功直接跳出流程,尝试次数耗尽直接退出
  • 补充空指针判断,文件打开失败直接返回,避免野指针操作

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 11:18:36