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

C++联系人列表程序ifstream搜索功能失效问题求助

让我来帮你排查这个搜索功能失效的问题,你的代码里有几个关键逻辑错误,我逐一给你分析并修复:

核心问题分析

  1. 完全错误的文件读取起始逻辑
    你在search()函数里用while(sr>>number)作为循环入口,但你的contacts.dat第一行是Name: john这种文本,根本不是数字——这会导致循环直接跳过,连一次迭代都不会执行,自然找不到任何联系人。

  2. 号码存储与读取的类型不匹配
    添加联系人时,你把号码存成了带+98前缀的字符串(比如+98911111111),但搜索时却用long int number去读取。+号不是整数的合法字符,这会直接导致读取失败;而且即使没有前缀,11位的长号码也可能超出long int的存储范围,引发溢出问题。

  3. 未处理文件中的标签文本
    文件里的内容是标签: 值的格式(比如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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 00:42:27