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

C++编译无错但无输出求助:账号文件读取模块异常

C++账号密码存储程序:文件读取无输出问题修复

问题描述

我正在编写一个用于接收并存储账号密码到文件的C程序(文件写入部分尚未完成,后续补充),但代码中的文件读取模块导致程序无输出,尽管在VS Code中使用clang编译器(基于C++20标准)编译无错误。坦白说,我对自己写的代码理解并不透彻(只是跟着YouTube视频编写),肯定存在疏漏。以下是我的代码供参考:

#include <iostream>
#include <cstdio>
#include <vector>
#include <fstream>

using namespace::std;

class user {
    private:
        string username;
        string password;
    public:
        user(string user, string pass) {
            username = user;
            password = pass;
        }
        void SetUsername(string user) {
            username = user;
        }
        void SetPassword(string pass) {
            password = pass;
        }
        void ChangeUsername(string user) {
            username = user;
        }
        void ChangePassword(string pass) {
            password = pass;
        }
        string GetUsername() {
            return username;
        }
        string GetPassword() {
            return password;
        }
};

int main() {
    string listUsernames[1000];
    string listPasswords[1000];
    vector <user>list;
    string username;
    string password;
    string prompt;
    bool loginSuccess = false;
    bool success = false;
    int counter = 0;
    int lines = 0;

    /*
    This part is like messsing it up
    Starting from here:
    */
    ifstream file;
    file.open("usernames.txt");
    while(!file.eof()) {
        getline(file, listUsernames[lines]);
        lines++;
    }
    file.close();

    lines = 0;
    file.open("passwords.txt");
    while(!file.eof()) {
        getline(file, listPasswords[lines]);
        lines++;
    }
    file.close();

    for(int i = 0; i < lines; i++) {
        user oldUser(listUsernames[i], listPasswords[i]);
        list.push_back(oldUser);
    }
    /*
    Ending here
    */

    cout << "\tWelcome user! Please choose to login or create an account below.\n";
    do{
    cout << "\tType \"Login\" to login or \"Create\" to create a new account\n";
    cin >> prompt;
        if(prompt == "Login") {
            do{
                cout << "Username: ";
                cin >> username;
                cout << "Password: ";
                cin >> password;

                for(int i = 0; i < list.size(); i++) {
                    if(username == list[i].GetUsername() && password == list[i].GetPassword()) {
                        cout << "Hello " << list[i].GetUsername() << "!\n\n";
                        loginSuccess = true;
                        success = true;
                    }
                }
                if(!loginSuccess) {
                    cout << "Incorrect username or password";
                    counter++;
                    if(counter < 2) {
                        cout << ", please try again.\n";
                    }
                    else {
                        cout << "\nMaybe you should try creating an account! \n";
                    }
                }
            } while(!loginSuccess && counter < 2);
        }
        else if(prompt == "Create") {
            string newUsername;
            string newPassword;
            cout << "What would you like your username to be? Please enter: ";
            cin >> newUsername;
            cout << "What would you like your password to be? Please enter: ";
            cin >> newPassword;  
            user newUser(newUsername, newPassword);
            list.push_back(newUser);
            cout << "Success!\n";
            ofstream myfile;
            myfile.open("usernames");
            myfile << newUsername;
            myfile.close();
            myfile.open("passwords");
            myfile << newPassword;
            myfile.close();
        }
        else {
            cout << "Sorry, that input was not understood\n";
            cout << "Please try again\n";
        }
    } while(!success);
    return 0;
}

问题分析与修复方案

1. 文件读取的致命错误:while(!file.eof())误用

这种写法会导致多读一行空数据,因为eof()仅在尝试读取超出文件末尾后才会返回true。当最后一行读取完成时,eof()仍为false,循环会再执行一次,此时getline读取失败,但lines依然自增,导致数组中出现空字符串,甚至引发越界崩溃。

修复方式:将getline作为循环条件,读取成功才继续:

// 读取用户名文件
ifstream file("usernames.txt");
string line;
while (getline(file, line)) {
    listUsernames[lines] = line;
    lines++;
}
file.close();

// 读取密码文件同理
lines = 0;
file.open("passwords.txt");
while (getline(file, line)) {
    listPasswords[lines] = line;
    lines++;
}
file.close();

2. 文件写入的匹配与覆盖问题

  • 创建账号时写入的文件名是usernames/passwords,但读取时用的是usernames.txt/passwords.txt,文件名不匹配导致下次启动读不到数据。
  • 写入时直接覆盖文件,而非追加,每次创建新账号都会丢失旧数据。需用ios::app追加模式:
ofstream myfile;
myfile.open("usernames.txt", ios::app); // 追加模式
myfile << newUsername << endl; // 每行一个用户名,保证读取一致性
myfile.close();
myfile.open("passwords.txt", ios::app);
myfile << newPassword << endl;
myfile.close();

3. 数组越界风险

固定大小数组string listUsernames[1000]若超过1000行数据会崩溃,建议改用vector<string>动态存储:

vector<string> listUsernames;
vector<string> listPasswords;

// 读取用户名
ifstream file("usernames.txt");
string line;
while (getline(file, line)) {
    listUsernames.push_back(line);
}
file.close();

// 读取密码
file.open("passwords.txt");
while (getline(file, line)) {
    listPasswords.push_back(line);
}
file.close();

// 初始化用户列表时,取两个vector的最小长度避免不匹配
size_t userCount = min(listUsernames.size(), listPasswords.size());
for (size_t i = 0; i < userCount; i++) {
    user oldUser(listUsernames[i], listPasswords[i]);
    list.push_back(oldUser);
}

4. 登录逻辑的细节问题

  • 多次登录失败后counter未重置,重新选择登录会直接触发创建账号提示,需在进入登录分支时重置counter和loginSuccess:
if(prompt == "Login") {
    counter = 0;
    loginSuccess = false;
    do{
        // 原有登录逻辑
    } while(!loginSuccess && counter < 2);
}

5. 类的冗余函数优化

SetUsername和ChangeUsername功能完全重复,可合并为一个函数,减少冗余:

void setUsername(string user) {
    username = user;
}
// 删除ChangeUsername函数

修复后的完整代码

#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>

using namespace std;

class user {
private:
    string username;
    string password;
public:
    // 用初始化列表构造更高效
    user(string user, string pass) : username(user), password(pass) {}

    void setUsername(string user) {
        username = user;
    }
    void setPassword(string pass) {
        password = pass;
    }
    string getUsername() {
        return username;
    }
    string getPassword() {
        return password;
    }
};

int main() {
    vector<string> listUsernames;
    vector<string> listPasswords;
    vector<user> list;
    string username;
    string password;
    string prompt;
    bool loginSuccess = false;
    bool success = false;
    int counter = 0;

    // 读取用户名文件,增加文件打开检查
    ifstream file("usernames.txt");
    string line;
    if (file.is_open()) {
        while (getline(file, line)) {
            listUsernames.push_back(line);
        }
        file.close();
    }

    // 读取密码文件
    file.open("passwords.txt");
    if (file.is_open()) {
        while (getline(file, line)) {
            listPasswords.push_back(line);
        }
        file.close();
    }

    // 初始化用户列表,避免用户名密码行数不匹配
    size_t userCount = min(listUsernames.size(), listPasswords.size());
    for (size_t i = 0; i < userCount; i++) {
        user oldUser(listUsernames[i], listPasswords[i]);
        list.push_back(oldUser);
    }

    cout << "\tWelcome user! Please choose to login or create an account below.\n";
    do {
        cout << "\tType \"Login\" to login or \"Create\" to create a new account\n";
        cin >> prompt;

        if (prompt == "Login") {
            counter = 0;
            loginSuccess = false;
            do {
                cout << "Username: ";
                cin >> username;
                cout << "Password: ";
                cin >> password;

                // 找到匹配后立即退出循环,提升效率
                for (size_t i = 0; i < list.size(); i++) {
                    if (username == list[i].getUsername() && password == list[i].getPassword()) {
                        cout << "Hello " << list[i].getUsername() << "!\n\n";
                        loginSuccess = true;
                        success = true;
                        break;
                    }
                }

                if (!loginSuccess) {
                    cout << "Incorrect username or password";
                    counter++;
                    if (counter < 2) {
                        cout << ", please try again.\n";
                    } else {
                        cout << "\nMaybe you should try creating an account! \n";
                    }
                }
            } while (!loginSuccess && counter < 2);
        } else if (prompt == "Create") {
            string newUsername;
            string newPassword;
            cout << "What would you like your username to be? Please enter: ";
            cin >> newUsername;
            cout << "What would you like your password to be? Please enter: ";
            cin >> newPassword;

            user newUser(newUsername, newPassword);
            list.push_back(newUser);
            cout << "Success!\n";

            // 追加写入文件,增加文件打开检查
            ofstream myfile("usernames.txt", ios::app);
            if (myfile.is_open()) {
                myfile << newUsername << endl;
                myfile.close();
            }
            myfile.open("passwords.txt", ios::app);
            if (myfile.is_open()) {
                myfile << newPassword << endl;
                myfile.close();
            }
        } else {
            cout << "Sorry, that input was not understood\n";
            cout << "Please try again\n";
        }
    } while (!success);

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 19:07:03