从冒号分隔的文件中提取信息 - C ++

时间:2013-11-21 01:11:33

标签: c++ ifstream getline

我正在尝试从冒号分隔的文件中提取信息到类对象中。文件的每一行都以相同的格式设置。以下是该文件的前几行:

s:Charles:Babbage:80:530213286:1133764834:mechanical engineering:3.8
e:Marissa:Meyer:37:549114177:53321:ceo:4456000
s:Alonzo:Church:92:586312110:1100539644:mathematics:4.0
e:Dana:Ulery:74:573811211:23451:engineer:124569

这是一个学校项目,目的是教我们类继承。我们有一个基类Person和两个子类Student和Employee。我们应该将学生的信息导入并存储到Student对象中,并将员工存储到Employee对象中。我为每个类都有一个对象数组;我将学生排序为Student对象数组,对员工进行排序,并将所有人员添加到People对象数组中。

我不知道如何通过分隔符来获取每条信息。现在我正在尝试使用.getline,但它似乎并没有起作用。如何使用此函数(或其他函数)将分隔符之间的信息提取到char数组中?到目前为止,这是数据适用于员工的情况:

ifstream fin;
char* tempImport;
tempImport = new char[50];
int* tempIntArray;
tempIntArray = new int[10];
double tempDouble;
int tempInt;

  // get the specifier of student or employee
  fin.getline(tempImport, ':');

  if(tempImport[0]=='e'){
     // get first name
     fin.getline(tempImport, ':');
     employees[employeeIndex].setFirstName(tempImport);
     allPeople[personIndex].setFirstName(tempImport);
     // get last name
     fin.getline(tempImport, ':');
     employees[employeeIndex].setFirstName(tempImport);
     allPeople[personIndex].setFirstName(tempImport);
     // get age
     fin.getline(tempImport, ':');
     employees[employeeIndex].setAge(tempImport[0] - 0);
     allPeople[personIndex].setAge(tempImport[0] - 0);
     // get SSN
     fin.getline(tempImport, ':');
     for(int i=0;i<9;i++){
        tempIntArray[i] = tempImport[i] - 0;
        }
     employees[employeeIndex].setSsn(tempIntArray);
     allPeople[personIndex].setSsn(tempIntArray);
     // get Employee ID
     fin.getline(tempImport, ':');
     for(int i=0;i<5;i++){
        tempIntArray[i] = tempImport[i] - 0;
        }
     employees[employeeIndex].setEmpID(tempIntArray);
     // get title
     fin.getline(tempImport, ':');
     employees[employeeIndex].setTitle(tempImport);
     // get salary
     fin >> tempDouble;
     employees[employeeIndex].setSalary(tempInt);
     employeeIndex++;
     personIndex++;
     }

2 个答案:

答案 0 :(得分:2)

如果你原谅我这么说,你似乎已经被教导了“面向对象编程”最糟糕的模仿之一(尽管如果它有任何安慰,它也是一个相当普遍的模仿)。

就个人而言,我认为我写的东西有点不同。

我可能首先要删除所有setSalarysetTitle等等。他们对OOP应该做的事情有着可怕的歪曲,在可读性方面失去了很多,而在封装

该类不应提供成员函数来操作类的所有成员,而应提供更高级别的成员来从流中重构自身的实例。

当你获得数据时,你可能想为你的People / Employees / Students数组创建单独的对象。相反,每个项目将进入员工或学生的阵列。然后People将只是指向其他两个数组中项目的指针数组。

关于读取数据的细节:我个人可能会编写一个将:分类为空格的ctype类,然后只读取数据。对于您的课程,您可能希望坚持使用getline

class Person { 
    virtual std::istream &read(std::istream &is);

    friend std::istream &operator>>(std::istream &is, Person &p) { 
        return p.read(is);
    }
};

class Student : public Person { 
    std::string first_name;
    std::string last_name;
    std::string age;
    std::string ssn;
    std::string ID;
    std::string title;
    std::string salary;

    virtual std::istream &read(std::istream &is) { 
        std::getline(is, first_name, ':');
        std::getline(is, last_name, ':');
        std::getline(is, age, ':');
        // ...
        return is;
    }
};

有了这些,从文件中读取数据通常非常简单:

std::string t;
Employee e;
Student s;

while (std::getline(infile, t, ':'))
    if (t == "e") {
        infile >> e;
        Employees.push_back(e);
    }
    else if (t =="s") {
        infile >> s;
        Students.push_back(s);
    }

答案 1 :(得分:2)

当您致电ifstream::getline()时,您似乎错过了一个参数。看到: http://www.cplusplus.com/reference/istream/istream/getline/

您需要方法的3参数版本才能指定分隔符。当您调用2参数版本时,它会将':'解释为streamsize。 (基本上,':'只是解析为冒号的ASCII代码,因此该数字被传入。对于streamize,你真正想要的是tempImport缓冲区的长度。)

但是,如果我建议(并且您的作业允许),该函数的std::getline()版本可能会更好。 (它允许您使用std::string而不是char*,这是一种更多C ++方式的做法。此外,您不必担心输入是否大于缓冲区。 )这是关于它的文档: http://www.cplusplus.com/reference/string/string/getline/

所以基本上你可以这样做:

std::string tempImport;
std::getline(fin, tempImport, ':');

作为调试建议,您可以在每次调用getline()之后打印tempImport(无论您使用哪种类型)。在提交之前将其删除,但这些打印语句可以帮助您在此期间调试解析。

std::stderr << "getline(): " << tempImport << std::endl;

编辑:

关于下面的评论,我能够将其编译。 (它没有做任何有用的事情,但表明std::getline()确实存在并编译。)它是否为你编译?

#include <fstream>

int main (int argc, char** argv)
{
        std::ifstream ifs;
        std::string str;
        std::getline(ifs, str, ':');
        return 0;
}