使用运算符重载解析 .txt 文件

问题描述 投票:0回答:2

这是学校作业。我正在重载>>,以便我可以解析文本文件并将其分配给一个类。

由于某种原因,我只能从 .txt 文件中读取一个对象。

这是我对运算符重载的尝试:

std::istream &operator>>(std::istream &is, ExercisePlan &plan) {
    std::string name;
    int steps;
    std::string date;

    std::getline(is, name);
    is >> steps;
    is.ignore();
    std::getline(is >> std::ws, date);

    plan.setPlanName(name);
    plan.setGoalSteps(steps);
    plan.setDate(date);

    return is;
}

这是我调用运算符重载器的地方:

template<typename T>
void FitnessAppWrapper::loadDailyPlan(std::fstream &fileStream, T& plan) {
    fileStream >> plan;
}
void FitnessAppWrapper::loadWeeklyPlan(std::fstream &fileStream, DietPlan *weeklyPlan) {
    for(int i = 0; i < 7; i++){
        //loadDailyPlan(fileStream,weeklyPlan[i]);
        fileStream >> weeklyPlan[i];
    }
}

这是我的文本文件,ExercisePlans.txt

Morning Walk
5000
02/22/2024

Gym Session
6000
02/23/2024

Cycling
5500
02/24/2024

Swimming
7000
02/25/2024

Running
8000
02/26/2024

Yoga
4500
02/27/2024

Hiking
7000
02/28/2024

这是解析器读取的内容(我有一个显示信息的显示函数):

|Exercise Plan: Morning Walk
|Date: 02/22/2024
|Goal: 5000 Steps

|Exercise Plan: 
|Date: 
|Goal: 0 Steps

|Exercise Plan: 
|Date: 
|Goal: 0 Steps

|Exercise Plan: 
|Date: 
|Goal: 0 Steps

|Exercise Plan: 
|Date: 
|Goal: 0 Steps

|Exercise Plan: 
|Date: 
|Goal: 0 Steps

|Exercise Plan: 
|Date: 
|Goal: 0 Steps

我在调试器中查看了代码,我发现当我尝试读取第二个练习计划时,它只是停止读取文件?

如果需要的话,这是我的显示功能:

std::ostream &operator<<(std::ostream &os, const ExercisePlan &plan) {
    os << "|Exercise Plan: " << plan.getPlanName() << "\n";
    os << "|Date: " << plan.getDate() << "\n";
    os << "|Goal: " << plan.getGoalSteps() << " Steps\n";

    /*os << plan.getPlanName() << "\n";
    os << plan.getDate() << "\n";
    os << plan.getGoalSteps() << "\n";*/
    return os;
}

如果需要,这是我的课程:

class ExercisePlan {
private:
    int goalSteps;
    std::string planName;
    std::string date;
public:
    // ## SETTERS AND GETTERS
    int getGoalSteps() const;
    void setGoalSteps(int goalSteps);
    const string &getPlanName() const;
    void setPlanName(const string &planName);
    const string &getDate() const;
    void setDate(const string &date);

    // ## CONSTRUCTORS
    ExercisePlan();
    ExercisePlan(int steps, const std::string& name, const std::string& date);
    ExercisePlan(const ExercisePlan& other);

    // ## DESTRUCTOR
    ~ExercisePlan();

    // ## OTHER FUNCTIONS
    void editGoal();
    friend std::ostream& operator<<(std::ostream& os, const ExercisePlan& plan);
    friend std::istream& operator>>(std::istream& is, ExercisePlan& plan);
    friend std::fstream& operator<<(std::fstream &fileStream, ExercisePlan &plan);
};

我使用函数重载和运算符重载的原因是因为我有一个与ExercisePlan类似的类,称为DietPlan,并且有一个类似的.txt文件,我也需要解析它。

c++ parsing operator-overloading
2个回答
0
投票

这是您问题的简化代码。我猜您打算跳过每个数据之间的空格,但您在提取数据完成之前调用了

ifs.ignore()

#include <fstream>
#include <iostream>
#include <string>

int main() {
  std::ifstream ifs("ExercisePlans.txt");

  for (int i = 0; i < 7; ++i) {
    std::string name;
    int steps;
    std::string date;

    std::getline(ifs, name);
    ifs >> steps;
    ifs.ignore();  // WRONG. should be called after the following line
    std::getline(ifs >> std::ws, date);

    std::cout << "status of ifs: " << (ifs.good() ? "GOOD" : "ERR") << "\n";
    std::cout << name << " " << steps << " " << date << "\n\n";
  }

  return 0;
}

我测试了切换

std::getline(ifs>>std::ws,date)
并且
ifs.ignore()
有效。

此外,您还可以通过调用

ifs.good()
ifs.fail()
ifs.bad()
来检查流操作是否成功。通过我输入的上述代码看看流的状态如何变化。


0
投票

文件中每组信息之间有一个空行。

std::getline(is, name);

这会读取该空行,然后您尝试将名称读取为

int
并且流会进入失败状态。

您需要考虑输入流中每次提取之间的空行。

© www.soinside.com 2019 - 2024. All rights reserved.