2013-04-06 212 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 
{ 
    // ... 
}