C++联系人列表程序ifstream搜索功能失效问题求助
让我来帮你排查这个搜索功能失效的问题,你的代码里有几个关键逻辑错误,我逐一给你分析并修复:
核心问题分析
完全错误的文件读取起始逻辑
你在search()函数里用while(sr>>number)作为循环入口,但你的contacts.dat第一行是Name: john这种文本,根本不是数字——这会导致循环直接跳过,连一次迭代都不会执行,自然找不到任何联系人。号码存储与读取的类型不匹配
添加联系人时,你把号码存成了带+98前缀的字符串(比如+98911111111),但搜索时却用long int number去读取。+号不是整数的合法字符,这会直接导致读取失败;而且即使没有前缀,11位的长号码也可能超出long int的存储范围,引发溢出问题。未处理文件中的标签文本
文件里的内容是标签: 值的格式(比如Name: john),但你的代码直接尝试读取name和number,会把Name:当成名字的一部分,或者读取到完全错误的内容,导致名字匹配失败。
另外还有个小笔误:你在append()里写的是cnt << "number: +98"(小写n),但你提供的contacts.dat里是Number:(大写N),这也会导致读取时匹配不上标签。
修复后的完整代码
我调整了类成员变量类型、文件读写逻辑,还修复了main()里switch语句的break遗漏问题,新增了实用的优化项:
#include <iostream> #include <fstream> #include <string> #include <limits> // 用于更可靠的整行忽略 class contact{ private: std::string name; // 将号码改为string类型,适配带+号的格式,同时避免溢出 std::string number; public: void append(); void search(); }; void contact::append(){ std::cin.ignore(); std::ofstream cnt; cnt.open("contacts.dat", std::ofstream::app); // 检查文件是否成功打开 if (!cnt.is_open()) { std::cout << "Failed to open contacts file for writing!\n"; return; } std::cout << "Please enter the name\n"; std::getline(std::cin, name); // 统一标签为大写N,和现有文件格式一致 cnt << "Name: " << name << std::endl; bool flag = true; while(flag){ std::cout << "Enter the number (without +98):\n"; std::cin >> number; if(std::cin.good()){ try{ // 检查号码是否为空或全0 if(number.empty() || number == "0"){ throw std::invalid_argument("Invalid number"); } else{ cnt << "Number: +98" << number << "\n\n"; flag = false; } } catch (...) { std::cout << "Invalid entry!\n\a"; } } else{ std::cout << "Invalid entry, please enter a numeric string!\n\a" << std::endl; std::cin.clear(); std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); } } std::cout << "Added Successfully!\n"; cnt.close(); } void contact::search(){ std::cin.ignore(); std::ifstream sr; sr.open("contacts.dat"); // 检查文件是否成功打开 if (!sr.is_open()) { std::cout << "Failed to open contacts file for reading!\n"; return; } std::string search_name; bool found = false; std::cout << "Enter a name for finding its phone number\n"; std::getline(std::cin, search_name); std::string label; // 循环读取文件中的标签和对应内容 while(sr >> label){ if(label == "Name:"){ // 跳过标签后的空格,读取完整名字(支持带空格的名字) sr.ignore(); std::getline(sr, name); // 读取下一个标签(Number:) sr >> label; if(label == "Number:"){ sr >> number; // 匹配搜索的名字 if(name == search_name){ std::cout << "Name: " << name << std::endl; std::cout << "Number: " << number << std::endl; found = true; break; } } } // 跳过当前行剩余的内容,准备读取下一行 sr.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); } if (!found){ std::cout << search_name << " not found!\n"; } sr.close(); } int main(){ contact cont; int choice; while (true) { std::cout << "\nEnter Your Choice\n"; std::cout << "\t1. Add contact \n"; std::cout << "\t2. Find contacts \n"; std::cout << "\t3. Exit \n"; // 新增退出选项,避免死循环 std::cin >> choice; switch(choice){ case 1: cont.append(); break; case 2: cont.search(); break; case 3: std::cout << "Exiting program...\n"; return 0; default: std::cout << "\nInvalid Choice!\n\a"; } } }
额外优化说明
- 新增了文件打开失败的检查,避免程序静默崩溃;
- 支持带空格的名字(比如
Mary Ann),更符合实际使用场景; - 新增了退出选项,避免程序一直处于死循环;
- 用
std::numeric_limits来忽略整行内容,比固定的10000更可靠。
内容的提问来源于stack exchange,提问作者alireza shojaei
相关产品推荐
相关产品推荐

