2017-06-09 2 views
-3

Ich habe das folgende Programm in C++. Das Ziel ist, einige Protokolle zu erhalten (die von der filedata-Variable stammen), die Protokolle zu analysieren und sie in der Objektliste zu speichern.Einfügen Objekt in C++ Liste

Der Teil, der das parse funktioniert gut. Aber ich habe ein Problem, wenn ich den geparsten Vektor iteriere und versuche, einige Elemente in der Liste zu speichern. Ich kann die Elemente erhalten (zum Beispiel: elements.at(0) Ich bekomme die erste Spalte (Zeitstempel) aber wenn ich auf meiner Liste speichern, speichern wir zweimal das Protokoll (in diesem Fall die filedata haben nur zwei Protokolle), aber wir speichern zwei Mal die SAME log

Mein cpp Programm.

#include <iostream> 
#include <sstream> 
#include <string> 
#include <vector> 
#include <iterator> 
#include <list> 

class UserLogRecord 
{ 
public: 
    std::string timestamp; 
    std::string id; 
    std::string name; 
    std::string data; 
}; 

std::vector<std::string> explode(std::string const & s, char delim) 
{ 
    std::vector<std::string> result; 
    std::istringstream iss(s); // sequence of characters 
    for (std::string token; std::getline(iss, token, delim);) 
    { 
    result.push_back(std::move(token)); //transfer token to vector 
    } 
    return result; 
} 

int main() 
{ 
    const char* filedata = 
    "1496843100;2017-06-07 13:45:00;000002D8;2600;user1\n" 
    "9999999999;2017-06-07 13:45:00;000002D9;2800;user2"; 

    std::vector<std::string> lines = explode(filedata,'\n'); 

    std::list<UserLogRecord* > userLogRecords; 
    UserLogRecord* userLogRecord = new UserLogRecord; 

    //vector 
    for(int i = 0; i < lines.size(); i++) 
    { 
    std::vector<std::string> elements = explode(lines[i], ';'); 
    userLogRecord->timestamp = elements.at(0); 
    userLogRecord->id = elements.at(2); 
    userLogRecord->name = elements.at(4); 
    userLogRecord->data = elements.at(3); 
    userLogRecords.push_back(userLogRecord); 
    } 

    //list of logs 
    std::list<UserLogRecord* >::const_iterator itLog = userLogRecords.begin(); 
    while (itLog != userLogRecords.end()) 
    { 
    std::cout << '\n' + (*itLog)->timestamp + '\n'; 
    std::cout << (*itLog)->id + '\n'; 
    std::cout << (*itLog)->name + '\n'; 
    std::cout << (*itLog)->data + '\n'; 
    ++itLog; 
    } 

    return 0; 
} 

Ausgang (wenn die Liste iterieren):

9999999999 
000002D9 
user2 
2800 

9999999999 
000002D9 
user2 
2800 

Erwartete Ausgabe:

1496843100 
000002D8 
user1 
2600 

9999999999 
000002D9 
user2 
2800 

Mein Programm speichert zwei Protokolle (dieser Teil ist ‚gut‘, ich habe nur zwei Protokolle), aber es ist immer das gleiche speichern (merkwürdig ist es das letzte Protokoll)

+0

Ich bearbeite bereits den Beitrag und den richtigen Code. Danke – rrpik93

+0

Haben Sie das debuggen? Fragen Sie sich selbst: * Was drängen Sie in Ihre Liste? * Es ist eine Liste von * Zeigern *. Der * gleiche * Zeiger wird wiederholt in die Liste geschoben. Es gibt keine eindeutigen Aufzeichnungen hier. Es gibt nur eins*. – WhozCraig

+0

Ich bin sicher, mit einem guten Debugger wirst du das Problem finden. Tipp: Sehen Sie sich Ihr Objekt 'userLogRecord' an. – Rene

Antwort

1

Sie nur eine UserLogRecord verwenden und einfach die modifizierende Daten, anstatt ein neues Element in der Liste hinzuzufügen.

std::list::push_back fügt eine Kopie eines Zeigers zu UserLogRecord hinzu, der für alle Iterationen der Schleife gleich bleibt. Der gleiche Zeiger wird mehrmals in der Liste gedrückt und daher haben alle Elemente die gleichen Daten.

Der folgende Code würde das Problem beheben. Ein neuer UserLogRecord wird für jede Iteration erstellt. Sie müssen jedoch daran denken, den zugewiesenen Speicher mit delete freizugeben, wenn Sie ihn nicht mehr benötigen.

//vector 
for(int i = 0; i < lines.size(); i++) 
{ 
    UserLogRecord* userLogRecord = new UserLogRecord; 

    std::vector<std::string> elements = explode(lines[i], ';'); 
    userLogRecord->timestamp = elements.at(0); 
    userLogRecord->id = elements.at(2); 
    userLogRecord->name = elements.at(4); 
    userLogRecord->data = elements.at(3); 
    userLogRecords.push_back(userLogRecord); 
} 
+1

Besser noch, verwenden Sie eine 'std :: list ' und beenden Sie die Verwendung nackter Zeiger an erster Stelle. Es gibt * null * Beweise, dass es überhaupt in diesem Code * gut ist *. – WhozCraig

+0

Hallo. Danke für die Antwort. Es funktioniert. Ich bin neu mit C++, manchmal habe ich diese Fehler. Ja, ich habe das Löschen vergessen (und es ist sehr wichtig). Hexenplatz muss ich löschen? Weil ich nicht in die Vektor-Iteration einsteigen kann, aber es ist nur der Ort, an dem ich Zugriff auf userLogRecord haben kann, weil ich drinnen für deklariere. Außerhalb habe ich keinen Zugang – rrpik93

+0

Sein nur ein Testcode dieses Beispiel. Ich baue eine Echtzeit-API und in diesem Fall brauche ich Zeiger – rrpik93