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
相关产品推荐
相关产品推荐

