Probleme mit vector



  • Rookie1 schrieb:

    ...Bei der Ausgabe wird aber bei allen Teams der Name des zuletzt eingelesenen Teams ausgegeben. Wenn ich jetzt aber folgenden Code anwende...werden die Teamnamen richtig gespeichert!

    1. Wo ist die Ausgebenfunktion, ich tippe eher da auf einen Fehler
    2. Warum versuchen sich eigentlich alle an C-Strings statt an std::string der deutlich weniger Anfängerfehler mit sich bringt (Ich hoffe du hast auch einen Destruktor um den Speicher wieder freizugeben wenn du schon mit Pointern arbeitest).

    Rookie1 schrieb:

    Wo liegt das Problem? Es spielt doch keine Rolle ob das push_back in einer while-Schleife ausgeführt oder nicht. Ich habe zuerst gedacht es läge an den Pointern und alle Pointer zeigen auf die selbe Adresse (darum die selben Werte), aber wieso funktioniert dann das zweite Beispiel? Ist ja eigentlich dasselbe!

    3. Es liegt wohl ein Fehler in der Benutzung von std::vector in den Bereichen vor die du nicht gepostet hast (Wäre auch gut wenn du an sich keine Fehler wie "Teams.push_back(new Team(Zeile);" postest, wo z.B. die schließende Klammer fehlt).

    cu André



  • Spontan würde ich sagen

    while(!feof(NameFile))
    {
    // hier musst du für die Zeile neuen speicher allociren
    Zeile = new char[...];
    //Lese Zeile mit Teamname aus
    Teams.push_back(new Team(Zeile);
    }
    


  • Der Konstruktor von Team:

    Team(char* strName) {this->Name = strName;}
    
    void TeamDB::ZeigeInhaltDB()
    {
    cout << "Show All Teams" <<endl;
    for (i=0;i < Teams.size();i++)
    {
    cout << i << " "<< Teams[i]->getName() << endl;
    }
    }
    

    Team::getName() gibt nur mit einem return den Teamnamen zurück.

    Ich würde fast wetten das du dem Konstruktor von Team nur einen Pointer übergibst, den du auch so in Team speicherst. Somit verweisen nachher alle Pointer auf die gleiche Adresse. Vermutlich auch noch eine temporäre Variable in der Methode zum Auslesen.

    Dass das Problem bei den Pointern liegt habe ich auch vermutet, aber wieso läft denn das 2.Beispiel??? 😕



  • @Ramsis: Genau das wars. Es funktioniert jetzt. Vielen dank!



  • Nicht so schnell vieleicht ist es besser diese Speicherallokierung
    in der klasse Team zu machen.



  • Also etwa so?

    Team(char* strName)
    {
    this->Name = new char[20];
    this->Name = strName;
    }
    


  • Rookie1 schrieb:

    Also etwa so?

    Team(char* strName)
    {
    this->Name = new char[20];
    this->Name = strName;
    }
    

    Da hast du 1. das gleiche Problem immernoch und 2. ein Speicherleck. 😉

    Team() : Name(0){ }
    Team(char* strName){
      this->Name = new char[strlen(strName)+1];
      strncpy(this->Name, strName, strlen(strName)+1);
    }
    ~Team(){
      if (Name) delete[] Name;
    }
    

    So in eta.



  • Oh man, da hab ich ja noch einige (Lern-)Arbeit vor mir! 😮

    Aber wenigstens bin ich jetzt mal aus meiner Gedanklichen Sackgasse raus und weiss wo mein Problem liegt. Nochmals vielen Dank für die Hilfe.



  • Fellhuhn schrieb:

    Team() : Name(0){ }
    Team(char* strName){
      this->Name = new char[strlen(strName)+1];
      strncpy(this->Name, strName, strlen(strName)+1);
    }
    ~Team(){
      if (Name) delete[] Name;
    }
    

    So in eta.

    Wenn Du Anfänger bist und C++ (nicht C) lernen willst, dann eher so:

    Team() { }
    Team(string const& strName)
       : Name(strName) { }
    
    private:
    string Name;
    


  • Oder du einfach nicht gerne so langen Code schreiben willst aber doch gerne die Basics lernen willst:

    Team(const char* name)
        : m_name(new char[std::strlen(name) + 1])
    {    
        std::strcpy(m_name, name); 
    }
    
    ~Team()
    {
        delete [] m_name;
    }
    

    und das ganze kurz erklären:
    Team-Konstruktor bekommt einen const char-Zeiger übergeben, da du ja nichts an dem String verändern willst sondern ihn kopieren willst(damit du sicher gehen kannst das er auch noch existiert!).

    Nun wird in der Initialisierungsliste m_name ein Speicherbereich aufm Heap zugewiesen von char * (länge des Strings + 1(für Nullterminierungszeichen!)).

    Damit kannst du sichergehen das dein String name auch in m_name reinpasst und kannst ihn einfach kopieren (std::strcpy).

    Da du Speicher aufm Heap angefordert hast und somit dieser nicht automatisch freigeben wird, musst du diesen selbst freigeben. Da ein Array delete [] anstatt delete.

    Soweit sollte das als Erklärung reichen!

    Noch eine Frage. Warum packst du in deinen vector denn Zeiger von Team? (wenn du das machst musst du dich wieder um's aufräumen kümmern!)



  • asc schrieb:

    2. Warum versuchen sich eigentlich alle an C-Strings statt an std::string der deutlich weniger Anfängerfehler mit sich bringt

    Weil "alle" Opfer von solch schwachsinnigen "C/C++"-Büchern sind deren Autoren meinen C++ sei eine Fortsetzung von C und nicht mitgekriegt haben dass es eine Standardbibliothek mit std::string etc. gibt. Diese Autoren haben einfach nicht mitbekommen dass sich C++ in den letzten 15-20 Jahren so weit von C entfernt hat dass const char* - Gefrickel, printf() &Co in den meisten Fällen nurnoch Altlasten sind. Wenigstens hat er in seiner Ausgabefunktion cout benutzt 😉



  • pumuckl schrieb:

    ...Autoren meinen C++ sei eine Fortsetzung von C und nicht mitgekriegt haben dass es eine Standardbibliothek mit std::string etc....

    ... und oftmals der Ansicht sind, dass Anfänger dieselbe Sch*** fressen müssten, die ihnen damals auch schon nicht geschmeckt hat (weil "man nur so wirklich versteht, was da passiert" = "den Orden 'Programmier' verliehen bekommen darf").

    Gruß,

    Simon2.


Anmelden zum Antworten