C++ FileIO功能实现异常求助:文件名无效及内容显示问题
C++文件IO功能修复:文件名无效与姓氏显示问题解决
问题概述
- 控制台仅在初始时显示文本文件中的姓名字符串,后续输入新姓名后该内容实际未存入程序数据结构,导致无法被后续操作调用
- 文件名输入功能无效,程序始终读取硬编码的
File.txt文件
问题根源与修复方案
1. 文件名硬编码问题
原代码直接使用File.open("File.txt");,完全忽略用户输入的文件名变量line。修复时需替换为用户输入的文件名,并增加文件打开失败的判断逻辑。
2. 文件内容未存入程序数据结构
原代码仅将文件内容输出到控制台,未将这些姓名添加到names向量中,导致后续操作无法访问这些数据。需在读取每一行后,将姓名处理为程序所需格式(last, first)并加入向量。
3. 输入顺序导致的读取异常
原代码先调用Menu(),其中的cin.ignore()会清空输入缓冲区,导致后续的文件名输入被跳过。需调整顺序,先获取文件名,再进入菜单循环。
修复后的完整代码
#include <iostream> #include <string> #include <vector> #include <sstream> #include <fstream> using namespace std; // function declarations int Menu(); void processName(string name, vector<string> &names, int &count); void displayName(vector<string> &names, int count); string getLastNames(vector<string> &names, int count); int main() { vector<string> names; int count = 0; ifstream File; string line; // 先获取文件名 cout << "Enter file name: "; getline(cin, line); // 使用用户输入的文件名打开文件 File.open(line); if (!File.is_open()) { cout << "Failed to open file: " << line << endl; } else { // 读取文件每一行并处理姓名 while (getline(File, line)) { processName(line, names, count); // 输出已处理的姓名 cout << names.back() << endl; } File.close(); } // 进入菜单循环 int choice = Menu(); while (choice != 0) { switch (choice) { case 1: { string name; cout << "Enter name: "; getline(cin, name); processName(name, names, count); } break; case 2: { displayName(names, count); } break; case 3: { cout << getLastNames(names, count) << endl; } break; case 0: { return 0; } break; } choice = Menu(); } return 0; } // 提取姓名处理逻辑为独立函数,复用文件读取和手动输入的场景 void processName(string name, vector<string> &names, int &count) { // 处理姓名格式为last, first int pos = name.find(' '); if(pos != string::npos) { string first = name.substr(0, pos); string last = name.substr(pos+1); name = last + "," + first; } names.push_back(name); count++; } // 菜单函数 int Menu() { int choice; cout << "\n1. Add a name" << endl; cout << "2. Display names " << endl; cout << "3. Show all Last Names" << endl; cout << "0. Quit" << endl; cout << "Enter a option: "; cin >> choice; while (choice < 0 || choice > 3) { cout << "Choice not on list: "; cin >> choice; } cin.ignore(); return choice; } // 生成姓氏字符串 string getLastNames(vector<string> &names, int count) { stringstream ss; for (int i = 0; i<count; i++) { int pos = names[i].find(','); if (pos != string::npos) { ss << "\"" << names[i].substr(0, pos) << "\", "; } else { ss << "\"" << names[i] << "\", "; } } string result = ss.str(); // 移除最后多余的逗号和空格(可选优化) if (!result.empty()) { result.pop_back(); result.pop_back(); } return result; } // 显示所有姓名 void displayName(vector<string> &names, int count) { if (count == 0) { cout << "No names to display" << endl; return; } for (int i = 0; i<count; i++) { cout << names[i] << endl; } }
修复说明
- 新增
processName函数,统一处理姓名格式转换逻辑,避免代码重复 - 调整输入顺序,先获取文件名再显示菜单,解决输入缓冲区干扰问题
- 替换硬编码文件名,使用用户输入的文件名打开文件,并增加打开失败提示
- 文件读取的姓名会被存入
names向量,后续操作(添加新姓名、显示姓名、生成姓氏列表)都能包含这些数据 - 优化
getLastNames函数,移除结果末尾多余的逗号和空格
内容的提问来源于stack exchange,提问作者radwave
相关产品推荐
相关产品推荐

