C++ 从文本文件创建对象

C++ Creating an object from text file

首先让我首先向 post 经常来这里的人说声谢谢,在过去的几年里,我通过搜索这个网站获得了大量知识。

好吧,之前有人问过这个问题,但我有一个轻微的扭曲,我无法开始工作。

这是我的结构。

struct person
{
    string Sex;
    string Name;
    string Match;
    int phoneNumber;
    int numInterests;
    vector<string> interests;
};

作业设计为 "Dating Program",匹配具有相似兴趣的异性。

下面是一个遵循这种格式的示例文本文件:

"Sex" "Name" "Phone Number" "Number of Interests" "List of interests" "Match (if a match is found)"

M Tyler 1234567890 3 soccer football tv Jess
F Lyns 1234567890 3 hockey sex movies
F Jess 1234567890 3 soccer football tv Tyler
M Taylor 1234567890 3 hockey sex movies

在该示例文件中,Jess 和 Tyler 匹配。 到目前为止,这是我的功能...

void LoadClients(std::ifstream &file,vector<person>& peps)
{
    string sex,name,interests,line, match;
    double phone,ni;
    person p;
    for(int i=0;i<maxPeople("Clients.mf"); i++){
        file>>sex>>name>>phone>>ni;
        p.Sex = sex;
        p.Name = name;
        p.phoneNumber = phone;
        p.numInterests = ni;
        for (int i=0; i<ni; i++){
            file >> line;
            p.interests.push_back(line);
        }
        file >> match;
        p.Match = match;
        peps.push_back(p);

       // person p;
        //istringstream iss( line );
    }

};

函数编译但根本无法正确读取。这是我剩下的工作,如果你想看...

int maxPeople(const char* file)///Just returns the number of lines in the file
{
    ifstream inFile(file);
    int c = count(istreambuf_iterator<char>(inFile),
            istreambuf_iterator<char>(), '\n');
    return c;
}
int main()
{
    int numberOfClients=maxPeople("Clients.mf");
    ifstream file("Clients.mf");

    vector<person> peps;
    LoadClients(file,peps);

    return 0;
}

我的函数 LoadClients 是根据我在此处找到的优雅答案建模的:Reading a string and integers

我所要求的只是如何获取此函数以从文本文件中创建矢量或人员数组。

最终程序将具有附加功能 "NewClient"、"UnMatch"、"PrintMatched" 和 "PrintSingles",但我认为我可以处理这些。非常欢迎任何提示:)

感谢阅读!

编辑1: 使用这种格式。

void LoadClients(std::ifstream &file,vector<person>& peps)  
{  
    person p;  
    string line;  
    while( getline( file, line ) )  
    {  
        istringstream iss( line );  
        iss >> p.Sex >> p.Name >> p.phoneNumber >> p.numInterests;  
        for(int i=0;i<p.numInterests;i++){  
            string interest;  
            iss >> interest;  
            p.interests.push_back(interest);  
        }  

    }  
}; 

我决定暂时跳过 "match"。当我从 main 访问对象时出现分段错误。

ifstream file("Clients.mf");

vector<person> peps;
LoadClients(file,peps);
for(int i=0; i<numberOfClients;i++){
    cout << peps[0].Name;
}

Phone 和 ni(我假设是兴趣数量)不应该加倍。我会让 Phone 成为一个字符串,而 ni 成为一个 int(有些人会认为无符号但足够接近)。

Double 和 Float 是 'lossy' 数据类型,不适用于计数或 phone 数字。

你实际上并没有说出行为是什么以及你期望它是什么。 我假设您的负载正在失控,这是因为这条线:

file >> match;

你不知道该行有没有,所以它可能会接下一行的第一个工作。

我会切换到使用 getLine 和字符串流,并在提取匹配之前检查该行是否为空(IE 字符串流是否在末尾)。

因为您的记录输入是基于行的,所以使用基于行的 reader。该程序现在的问题是它假定始终存在匹配项。但是在输入文件的第二行,没有匹配项。因此,将读取下一个 space 分隔的文本。

我喜欢这种从文件中解析行的方法,因为它很简单:

string line;
while( getline( file, line ) )
{
    istringstream iss( line );

    // Now, parse out of 'iss' instead of 'file'.
    person p;
    bool ok = false;
    if( iss >> p.Sex >> p.Name >> p.phoneNumber >> p.numInterests )
    {
        p.interests.reserve( p.numInterests );
        for( int i = 0; i < p.numInterests; i++ )
        {
            string interest;
            if( iss >> interest ) p.interests.emplace_back( interest );
        }

        ok = !iss.error();

        iss >> p.Match; // optional
    }

    if( ok ) peps.push_back( p );
}

您可以更进一步,为您的 Person 结构定义一个流输入运算符。然后,主读取循环看起来像:

person p;
iss >> p;

顺便说一句,不是 sex 成为 string 的好主意,除非你想让你的程序处理外星人......您的 int phoneNumber 可能有问题。如果你有 interests.size()numInterests 就是多余的。所以你可以做...

struct Person {
    enum class Gender {
        Unknown,
        Male,
        Female,
    };

    Gender gender;
    std::string name;
    std::string match;
    std::string phoneNumber;
    std::vector<std::string> interests;
};

现在,进入正题。该函数应该看起来像(没有检查和 C++11!)...

static Person::Gender readGender(std::ifstream &input) {
    char ch;
    input >> ch;
    switch(ch) {
        case 'M':
            return Person::Gender::Male;

        case 'F':
            return Person::Gender::Female;

        default:
            return Person::Gender::Unknown;
    }
}

void LoadClients(std::ifstream &file, std::vector<person> &out) {
    for(int i = 0; i < maxPeople("Clients.mf"); i++) {
        Person p;
        unsigned numInterests;

        p.gender = readGender(file);
        file >> p.name;
        file >> p.phoneNumber;
        file >> numInterests;
        for(unsigned i = 0; i < numInterests; i++){
            std::string interest;
            file >> interest;

            p.interests.push_back(interest);
        }

        file >> p.match;
        out.push_back(p);
    }
}

编辑:你应该有办法让程序区分是否有match,否则未定义的挫折会找你!

编辑:由于来自 OP 的评论,之前的评论无效。

编辑: 根据评论修正了一些错误。