2013-04-06 102 views
3

我正在从文件中读取结构,我想将它们添加到结构向量中。 下面是它的外观和工作方式:向量的结构:添加元素C++

typedef struct 
{ 
    int ID; 
    string name; 
    string surname; 
    int points; 
} 
Student; 

int main() 
{ 
    ifstream theFile("test.txt"); 
    std::vector<Student*> students; 

    Student* s = new Student(); 

    while(theFile >> s->ID >> s->name >> s->surname >> s->points) 
    { 
     studenti.push_back(s); // here I would like to add this struct s from a file 
    } 

// here I want to print each struct's values on the screen, but the output is always ONLY last struct N times, and not all of them, each only once 


    std::vector<Student*>::const_iterator it; 
    for(it = students.begin(); it != students.end(); it+=1) 
    { 
     std::cout << (*it)->ID <<" " << (*it)->name << " " << (*it)->surname <<" " << (*it)->points <<endl; 
    } 

我应该怎么做,我可以加我的结构为载体,并将其打印正常(本刊只是一种检查真的,如果结构是正确加载成矢量)?

+2

为什么哦为什么'typedef'? – 2013-04-06 11:40:19

+1

什么是文件格式?每个学生的名字都由两个字组成吗? – 2013-04-06 11:42:09

+0

请注意,您没有结构向量,您有一个指针向量。所有这些指向相同的对象... – juanchopanza 2013-04-06 11:43:57

回答

8

这里是代码的外观在现代C++:

#include <string> 
#include <istream> 
#include <vector> 

struct Student 
{ 
    int ID; 
    std::string name; 
    std::string surname; 
    int points; 

    Student(int i, std::string n, std::string s, int p) 
    : ID(i), name(std::move(n)), surname(std::move(s)), points(p) {} 
}; 

std::vector<Student> read_students(std::istream & is) 
{ 
    std::vector<Student> result; 

    std::string name, surname; 
    int id, points; 

    while (is >> id >> name >> surname >> points) 
    { 
     result.emplace_back(id, name, surname, points); 
    } 

    return result; 
} 

用法:

#include <fstream> 
#include <iostream> 

int main() 
{ 
    std::ifstream infile("test.txt"); 
    auto students = read_students(infile); 

    // ... 
} 
+1

我尝试emplace_back()一个结构与四个字段,如上例中,但在编译期间,我得到错误'没有匹配的构造函数',所以你提供的例子似乎是不正确的。 – kometen 2016-02-29 16:33:43

+2

@kometen:你说得对,'学生'需要一个合适的构造函数。我加了一个。或者,您可以说'result.push_back({id,name,surname,points});'并且您不需要为该版本添加构造函数。 – 2016-03-01 03:15:27

+0

非常优雅的解决方案。谢谢。 – kometen 2016-03-01 07:34:40

8

你的错误是使用指针

std::vector<Student> students; 

Student s; 
while(theFile >> s.ID >> s.name >> s.surname >> s.points) 
{ 
    students.push_back(s); 
} 

现在,它会工作。

问题在于您一遍又一遍重复使用了相同的指针。所以你最终得到一个指向同一个对象的指针向量。这将有价值的最后一个学生阅读英寸

这似乎是一个相当普遍的初学特征选择复杂的选择,当更简单的一个是正确的,所以我会有兴趣知道为什么你选择使用指针。

+2

+1为推荐不存储指针。 – 2013-04-06 12:39:13

+0

我认为如果我使用指针会更好,因为我需要稍后在程序中调用该列表上的方法。但我没有经验过指针,只是一个想法。不确定指针的优劣,tbh真的。 – Whizzil 2013-04-06 13:39:40

+0

您可以在不使用指针的情况下调用列表上的方法。它没有区别,例如'学生[I] .some_method();'。 – john 2013-04-06 18:25:56

0

既然你要存储指向学生,但不是在矢量学生。

Student* s = new Student(); 

while(theFile >> s->ID >> s->name >> s->surname >> s->points) 
{ 
    students.push_back(s); // here I would like to add this struct s from a file 
} 

您已经分配只有一个学生,每次你循环你一次又一次地阅读它。

相反,您应该在每个循环中分配一个新学生并读入新分配的内存。

Student* s; 
int tmpId, tmpPoints; 
string tmpname, tmpsur; 

while(theFile >> tmpId >> tmpname >> tmpsur >> tmpPoints) 
{ 
    s = new Student(); 

    s->ID = tmpId ; 
    s->name = tmpname; 
    s->sur = tmpsur ; 
    s->points= tmpPoints; 

    studenti.push_back(s); // here You push a pointer to the newly allocated student 
} 
else 
{ 
    // There is error reading data 
} 

不要忘记删除每个学生,当你不需要向量了。

0

您的代码不起作用,因为您每次都有一个Student对象并覆盖其成员。解决方法是每次创建一个新的Student对象并将指针传递给您的向量:

std::vector<Student*> students; 
int tmpId, tmpPoints; 
string tmpname, tmpsur; 

while(theFile >> tmpId >> tmpname >> tmpsur >> tmpPoints) 
{ 
    Student* s = new Student(); 
    s->ID = tmpId ; 
    s->name = tmpname; 
    s->sur = tmpsur ; 
    s->points= tmpPoints; 

    students.push_back(s); // push a pointer to new student object 
} 
else 
{ 
    // ... 
}