Probleme mit <vector> und while
-
Hallo zusammen,
bevor ich verrückt werde, frage ich hier mal nach, ob irgendjemand eine schlüssige Erklärung / Lösung für ein Problem hat, was mich aktuell beschäftigt. Das Problem an sich ist eigentlich recht unspektakulär. Ich möchte Chars aus einer Datei auslesen. Diese Chars werden dem Konstruktor einer Klasse übergeben und in dem erzeugten Objekt gespeichert. Um mir Arbeit zu ersparen, wollte ich einen <vector> zur Verwaltung der Objekte verwenden. Mein Problem ist jetzt das folgende:
Da ich zu Beginn nicht weiß, wie lang die Datei ist, will ich die Abarbeitung in einer While - Schleife packen, die endet, wenn das Dateiende erreicht ist. => klappt!
In jedem Durchlauf erzeuge ich 2 Objekte von meiner Klasse ClKnoten und übergebe dem Konstruktor (char literal[4]) => klappt!
Ist die Schleife dann aber fertig und will ich dann die chars aus den Objekten auslesen, hat der Vector zwar die richtige Anzahl erzeugt, aber aus irgendeinem Grund die Objekte überschrieben / kopiert, was auch immer...
Mache ich das Ganze nicht in einer Schleife, läufts wie geschmiert...
Hier mal das Ganz in Code:int count = 0; vector <ClKnoten> variablen; while(!feof(datei)) { fscanf(datei, "%s", &literal1); fscanf(datei, "%s", &literal2); variablen[count] = new ClKnoten(literal1); count++; variablen[count] = new ClKnoten(literal2); count++; }Habs auch schon mit push_back() und insert(pos, elem) des Vectors versucht, aber immer das gleiche Problem!
Hat da jemand eine Erklärung für?
Danke schon mal!
Patrick
-
Du kannst bei einem std::vector nicht einfach neue Elemente anlegen in dem du auf einen nicht vorhandenen Index zugreifst. Neue Elemente hinten anfügen (ganz ohne count) kannst du mit der Methode push_back.
Warum du pro Schleifendurchlauf jeweils immer 2 Elemente ausliest hab ich auch nicht verstanden

MfG SideWinder
-
Das compiliert ?
So sollte es gehenint count = 0; vector <ClKnoten*> variablen; // vector von pointer auf knoten while(!feof(datei)) { fscanf(datei, "%s", &literal1); fscanf(datei, "%s", &literal2); variablen.push_back( new ClKnoten(literal1)); count++; variablen.push_back( new ClKnoten(literal2)); count++; }
-
SideWinder schrieb:
Du kannst bei einem std::vector nicht einfach neue Elemente anlegen in dem du auf einen nicht vorhandenen Index zugreifst. Neue Elemente hinten anfügen (ganz ohne count) kannst du mit der Methode push_back.
Das hatte ich ursprünglich auch versucht. Hab auch probiert, den vector auf eine feste Anzahl an ELementen zu initialisieren á la
vector<ClKnoten> variablen(max_anzahl);Brachte aber leider auch nichts. Über das count motzt der Compiler auch nicht. Ich kann auch alle 4 ELemente (2 Durchläufe) ausgeben. Er überschreibt aber immer das jeweilige Element =>
noch mysteröser wird die Sache aufgrund der folgenden Ausgabe:variablen.push_back( new ClKnoten(literal1)); variablen.push_back( new ClKnoten(literal2));=> wenn die Schleife 2 mal durchgelaufen ist, habe ich in variablen[0]->name das gleiche (literal1) stehen wie in variablen[2]->name. Gleiches gilt für literal2 an den Vectorposition 1 und 3.
Ich habe bereits probiert, obs an den Inhalten der literale liegt, die werden aber korrekt eingelesen. und wenn ich die Ausgabe der variablen[i]->name in den Schleife mache, sind die auch korrekt => nur wenn ich da nachher drauf zugreife, finde ich nur Quatsch vor!SideWinder schrieb:
Warum du pro Schleifendurchlauf jeweils immer 2 Elemente ausliest hab ich auch nicht verstanden

Das mache ich, da ich pro Zeile in der Eingabedatei 2 Inhalte auslese. => Hab aber auch gerad zum Test mal nur ein Element ausgelesen => gleiches Problem!
Ich werd wahnsinnig!
-
"new" gibt einen zeiger zurück. d.h., es müsste vector<ClKnoten*> sein.
wenn du "vector<ClKnoten> variablen(max_anzahl);" benutzt, sind die elemente bereits angelegt, du musst nichts mehr "new"en.
-
Zeig mal den constructor von ClKnoten
Wette du machst sowasclass ClKnoten { public: ClKnoten( char * ch ) { name = ch; } protected: char * name; };Kurt
-
Bist nah dran. Konstruktor sieht wie folgt aus:
public: char * name; ClKnoten(char literal[4]){this->name = literal;}Hast du einen Verdacht? Wenn ja, bitte mit Erklärung! Verstehe immer gern, was ich da falsch gemacht habe!
-
ein char* ist nur ein zeiger auf char. da ist nur die addresse gespeichert, nicht die information selbst. wenn du den konstruktor aufrufst, zeigt also nur die membervariable "name" auf wasauchimmer du gerade gelesen hast. aber wenn das weg ist, zeigt "name" immer noch an dieselbe addresse-nur die information ist schon längst weg. du müsstest also z.b. std::string (header: <string>) verwenden.
-
Verwende fstream und string
-
Any schrieb:
Verwende fstream und string
Ich verwende aus dem Grund FILE, damit ich ie fscanf - Methoden verwenden kann. Eine Leseschleife für fstream war mir bei der Datenstruktur zu aufwendig. Habs jetzt aber so gemacht, dass ich im Konstruktor ne kleine Schleife gebaut hab, die mir die chars in einen String kopiert. Das funktioniert auch einwandfrei. War also das Pointer - Problem. Eigentlich offensichtlich, aber manchmal sieht man den Wald vor lauter Bäumen nicht!
Danke euch!
-
also ich finde "fin>>str;" wesentlich einfacher zu schreiben als "fscanf(fin,"%s",str);" - und außerdem ist die Variante mit strings sicherer im Umgang mit dem Speicherplatz.
-
CStoll schrieb:
also ich finde "fin>>str;" wesentlich einfacher zu schreiben als "fscanf(fin,"%s",str);" - und außerdem ist die Variante mit strings sicherer im Umgang mit dem Speicherplatz.
Hmmm, hatte von der Verwendung von >> im Zusammenhang mit fstreams noch nicht gehört. Aber lerne immer gern dazu. Ist wahrscheinlich ne Ableitung von istream, nehm ich an. Liest das wie fscanf() immer bis zum nächsten whitespace oder muss man dann andere modifikatoren verwenden?
-
Hängt davon ab welche Flags gesetzt sind. Die default Einstellung ist jedes ' ', '\n' und '\t' zu überspringen und dann Daten zu lesen. Kann man aber mit std::noskipws abschalten.
Also du hast:
int a,b; in>>a>>b;Wenn dein Stream nun am Anfang " 0 55 03 " enthielt wird er am Ende nur noch " 03 " enthalten. Leerzeichen können mit std::ws übersprungen werden.