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

C++文件IO实现按序号删除待办事项整行功能求助

解决C++待办事项列表的行删除问题

嘿,我明白你现在的困扰——用临时文件删行要么错删要么只删序号,这大概率是你的del函数逻辑没处理好行匹配和文件读写的细节。我来帮你把这个功能搞定,先看完整的修正代码,再给你拆解关键步骤。

首先,补上你没写完的add、view函数,同时重点修正del函数:

#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include <stdlib.h>
#include <algorithm>
using namespace std;

// Class for our add, delete, and view functions.
class Todo {
public:
    void add(string item);
    void del(string item);
    void view();
private:
    // 辅助函数:修剪字符串前后的空白字符
    string trim(const string& s) {
        auto start = s.begin();
        while (start != s.end() && isspace(*start)) {
            start++;
        }
        auto end = s.end();
        do {
            end--;
        } while (distance(start, end) > 0 && isspace(*end));
        return string(start, end + 1);
    }
};

int main () {
    Todo l;
    string item;
    char command;
lPlaceholder:
    cout << "\t\tYour ToDo List" << endl;
    cout << "Press + then enter your item to add to the list" << endl;
    cout << "Press - then enter your items serial number to remove" << endl;
    cout << "Press ? to display all items in your list" << endl;
    cout << "Press x to quit the program" << endl;
    cin >> command;
    if (command == '+' || command == '-') {
        getline(cin, item);
    }
    // Simple menu
    switch(command){
        case '+': l.add(item); goto lPlaceholder;
        case '-': l.del(item); goto lPlaceholder;
        case '?': l.view(); goto lPlaceholder;
        case 'x': exit (0);
        default: cout << "Invalid choice.\n"; goto lPlaceholder;
    }
}

// Add function
void Todo::add(string item) {
    // 先获取当前已有任务的数量,用来生成序号
    int count = 0;
    ifstream inFile("todo.txt");
    string line;
    while (getline(inFile, line)) {
        count++;
    }
    inFile.close();

    // 写入新任务,格式为 "序号. 任务内容"
    ofstream outFile("todo.txt", ios::app);
    if (outFile.is_open()) {
        outFile << count + 1 << ". " << trim(item) << endl;
        cout << "Task added successfully!\n";
        outFile.close();
    } else {
        cout << "Error opening file to add task.\n";
    }
}

// Delete function
void Todo::del(string item) {
    // 1. 解析用户输入的序号:先修剪空白,转成整数
    string numStr = trim(item);
    int targetLine;
    try {
        targetLine = stoi(numStr);
    } catch (...) {
        cout << "Invalid serial number! Please enter a number.\n";
        return;
    }

    // 2. 打开原文件和临时文件
    ifstream inFile("todo.txt");
    ofstream tempFile("temp.txt");
    if (!inFile.is_open() || !tempFile.is_open()) {
        cout << "Error opening files for deletion.\n";
        return;
    }

    // 3. 逐行读取,跳过目标行,写入临时文件并重新生成序号
    string line;
    int currentLine = 0;
    bool found = false;
    while (getline(inFile, line)) {
        currentLine++;
        if (currentLine != targetLine) {
            // 删除目标行后,后续行的序号要递减
            int newNum = currentLine - (found ? 1 : 0);
            // 提取原行的任务内容,重新拼接带新序号的行
            size_t dotPos = line.find(". ");
            if (dotPos != string::npos) {
                tempFile << newNum << ". " << line.substr(dotPos + 2) << endl;
            }
        } else {
            found = true;
            cout << "Task " << targetLine << " deleted successfully!\n";
        }
    }

    // 4. 关闭文件
    inFile.close();
    tempFile.close();

    // 5. 处理没找到目标行的情况
    if (!found) {
        cout << "No task found with serial number " << targetLine << ".\n";
        remove("temp.txt"); // 删除空的临时文件
        return;
    }

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

// View function
void Todo::view() {
    ifstream inFile("todo.txt");
    if (!inFile.is_open()) {
        cout << "Your todo list is empty!\n";
        return;
    }
    string line;
    cout << "\nYour ToDo Items:\n";
    while (getline(inFile, line)) {
        cout << line << endl;
    }
    inFile.close();
}

关键修正点解释:

  1. 输入解析与验证:

    • 新增trim辅助函数,清理用户输入里的多余空白(比如输入- 2时,item是" 2",trim后变成"2")。
    • 用stoi转换序号并捕获异常,避免非数字输入导致程序崩溃。
  2. 删除后重新生成序号:
    这是你最可能踩坑的地方!如果只是跳过目标行,后续行的序号会断层(比如删了第2行,第3行还是显示3)。写入临时文件时,我们会重新计算每一行的序号:找到目标行后,后续行的序号自动减1,保持列表序号连续。

  3. 完整的错误处理:
    增加了文件打开失败的判断,以及目标序号不存在时的提示,避免无效的文件替换操作。

  4. 菜单逻辑补全:
    在default分支加了goto lPlaceholder,避免输入无效命令后直接退出程序。

现在测试一下:输入- 2,程序会精准找到第2行并跳过它,同时将后面的任务重新编号写入临时文件,最后替换原文件,完美实现删除指定序号的整行任务。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:45:02