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

求助修复C++文本文件删除指定行时误删上方行的代码问题

问题

刚学编程不到一周,正在做学校的重要项目,用C++写的代码想把搜索和行删除功能结合起来,两个功能单独跑都正常,但结合后就出问题了——删除目标行的时候会把该行上方的所有行也一起删掉。比如输入James,找到Lebron James的记录,确认删除后,这条记录和它上面的所有行都没了。

文本文件内容:

  1. Barry Bonds 326598
  2. Michael Jordan 784512
  3. Lebron James 545689
  4. Steph Curry 878512
  5. Joe Montana 656231
  6. Deebo Samuel 783265
  7. Leonardo Dicaprio 123645

原代码:

#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <stdlib.h>
#include <sstream>
#include <vector>
#include <iterator>
#include <cassert>

using namespace std;

void search()
{
    struct employee 
    {
        string firstname;
        string lastname;
        string user_id;  
    };

    ifstream Myfile;
    Myfile.open("employeerecords.txt");
    ofstream temp;
    temp.open("temp.txt");

    vector<employee> employees;

    string deleteline;
    string line;
    string search;
    string confirm;
    int offset;

    cout << "\nType 'cancel' to return to menu\n\n";
    cout << "Enter Employee Name or ID: ";
    cin >> search;

    if (search == "cancel")
    {
        /*void hrmenu();
        hrmenu();*/
    } 
    else if (Myfile.is_open())
    {
        while (!Myfile.eof())
        {
            while(getline(Myfile, line))
            {
                if ((offset = line.find(search, 0)) != string::npos)
                {
                    istringstream ss(line);
                    istream_iterator<string> begin(ss), end;
                    vector<string> words(begin, end); 

                    assert(words.size() >= 3); 

                    int n = words.size() - 1;
                    employee e { words[0], words[n-1], words[n] };
                    for (int i = 1 ; i < n - 3 ; i++) e.firstname += " " + words[i];

                    employees.push_back(e);

                    for(auto && e : employees)
                        cout << "Employee Name: "<<e.firstname<< " "<<e.lastname << '\n'
                             << "User ID: "<<e.user_id << '\n'
                             << "-------------------" << '\n';

                    cout << "Is this the record you want to delete? (Y/N): ";
                    cin >> confirm;

                    if (confirm == "Y")
                    {
                        while(getline(Myfile, line))
                        {
                            if (line != search)
                            {
                                temp << line << endl;
                            }
                        }
                    }
            
                    temp.close();
                    Myfile.close();
                    remove("employeerecord.txt");
                    rename("temp.txt","employeerecords.txt"); 
                }
            }
        }
        Myfile.close();
    }
    else
        cout << "File opening error" << endl;
    return;
}

int main()
{
    void search();
    search();
}
问题分析与修正方案

核心问题

  • 丢失目标行之前的内容:找到匹配行后直接读取文件剩余内容写入临时文件,完全没处理匹配行之前的行,导致这些行全部丢失。
  • 删除判断逻辑无效:用line != search判断是否保留行,但search是关键词(比如James),文件里的行是完整记录(比如3. Lebron James 545689),两者永远不相等,等于没过滤任何行。
  • 流程混乱:找到第一个匹配行就直接关闭文件、替换原文件,后续匹配行无法处理;嵌套的while循环和提前关闭文件的操作进一步打乱逻辑。
  • 姓名拼接错误:for (int i = 1 ; i < n - 3 ; i++)的循环条件错误,无法正确处理带空格的全名(比如Leonardo Dicaprio)。

修正后的代码

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <iterator>
#include <cassert>

using namespace std;

struct Employee 
{
    string fullName;
    string userId;
    string originalLine; // 保存原始行,用于精准判断删除
};

void searchAndDelete()
{
    ifstream inFile("employeerecords.txt");
    if (!inFile.is_open())
    {
        cout << "文件打开失败" << endl;
        return;
    }

    string searchTerm;
    cout << "\n输入'cancel'返回菜单\n\n";
    cout << "请输入员工姓名或ID: ";
    cin >> searchTerm;

    if (searchTerm == "cancel")
    {
        // 此处可添加返回菜单的逻辑,比如调用hrmenu()
        return;
    }

    vector<Employee> matchedEmployees;
    vector<string> allLines;
    string line;

    // 第一步:读取所有行,同时收集匹配记录
    while (getline(inFile, line))
    {
        allLines.push_back(line);
        if (line.find(searchTerm) != string::npos)
        {
            istringstream ss(line);
            vector<string> words((istream_iterator<string>(ss)), istream_iterator<string>());
            assert(words.size() >= 3);

            Employee emp;
            emp.originalLine = line;
            emp.userId = words.back();
            // 拼接全名:从序号后的第一个单词到倒数第二个单词
            for (size_t i = 1; i < words.size() - 1; ++i)
            {
                if (i > 1) emp.fullName += " ";
                emp.fullName += words[i];
            }
            matchedEmployees.push_back(emp);
        }
    }
    inFile.close();

    if (matchedEmployees.empty())
    {
        cout << "未找到匹配的记录" << endl;
        return;
    }

    // 显示匹配记录并确认删除
    cout << "找到以下匹配记录:\n";
    for (size_t i = 0; i < matchedEmployees.size(); ++i)
    {
        cout << "序号" << i+1 << ":\n";
        cout << "员工姓名: " << matchedEmployees[i].fullName << '\n';
        cout << "用户ID: " << matchedEmployees[i].userId << '\n';
        cout << "-------------------\n";
    }

    cout << "是否删除以上所有匹配记录? (Y/N): ";
    string confirm;
    cin >> confirm;

    if (confirm != "Y" && confirm != "y")
    {
        cout << "取消删除操作" << endl;
        return;
    }

    // 第二步:写入临时文件,跳过需要删除的行
    ofstream outFile("temp.txt");
    if (!outFile.is_open())
    {
        cout << "临时文件创建失败" << endl;
        return;
    }

    for (const string& l : allLines)
    {
        bool shouldDelete = false;
        for (const Employee& emp : matchedEmployees)
        {
            if (l == emp.originalLine)
            {
                shouldDelete = true;
                break;
            }
        }
        if (!shouldDelete)
        {
            outFile << l << '\n';
        }
    }
    outFile.close();

    // 替换原文件
    remove("employeerecords.txt");
    rename("temp.txt", "employeerecords.txt");

    cout << "删除成功" << endl;
}

int main()
{
    searchAndDelete();
    return 0;
}

修正说明

  • 先读取所有行:把文件内容全部存入vector,避免处理时丢失前面的行,同时能完整收集所有匹配记录。
  • 精准删除判断:用原始行内容匹配是否删除,确保只删掉用户确认的目标行。
  • 正确拼接全名:遍历序号后的所有名字单词,支持带空格的全名。
  • 流程拆分清晰:分成读取收集、确认删除、写入临时文件三个独立步骤,逻辑更易懂,避免嵌套混乱。
  • 完善错误提示:增加文件打开失败、无匹配记录等场景的提示,提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 20:14:56