Ein- und Ausgabe von Txt Datei

hawk2

Grünschnabel
Hallo Community,

ich habe ein kleines Problem mit meinem code. Und zwar will ich aus einer Txt-Datei (Stadtname, Einwohnerzahl,Land,Erdteil) einlesen und ausgeben. Diese sind jeweils durch ein Semikolon getrennt.

Bsp: Madrid; 3.213.271; Spanien; Europa

Wenn ich das Programm compile wird zwar aus der Datei gelesen, aber leider wird die Datei nicht ausgegeben, sondern nur, dass die Datei erfolgreich gelesen wurde. Auch der Platz, der für die Datei vorgesehen ist, wird vom Compiler freigelassen, jedoch nur ein schwarzer bildschirm und keinerlei Ausgabe.Ich finde den Fehler einfach nicht, ich bin euch sehr Danbar für eure Hilfe.

Hier mein Code:

Code:
MAIN DATEI:

#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include "Town.h"
#include <sstream>

using namespace std;

vector<string>split(const string &s, char delim = ',')
{
   vector<string> elems;

   stringstream ss(s);
   string item;
   while (getline(ss,item,delim))
   {
       elems.push_back(item);
   }
   return elems;
}

void datenEinlesen(vector<Town>vtown)
{
   string trash;
   string zeile;

   ifstream f;
   f.open("Town.txt");

   if (f.fail())
   {
       cout << "datei kann nicht gelesen werden!" << endl;
       return;
   }

   cout << "Lese Datei!" << endl;

   getline(f, trash); // Löschen der ersten 3 Zeilen in Textdatei
   getline(f, trash);
   getline(f, trash);

   while (getline(f, zeile)) // Lese bis zum Dateiende = EOF
   {
       vector<string> columns = split(zeile, ';');
       Town ctown;

       ctown.getName() = columns[0];
       ctown.getEinwohnerzahl() = columns[1];
       ctown.getLand() = columns[2];
       ctown.getErdteil() = columns[3];

       vtown.push_back(ctown);
   }
   f.close();
   
   for (unsigned int i = 0; i < vtown.size(); i++)
   {
       cout << vtown[i].getName() << vtown[i].getEinwohnerzahl() << vtown[i].getLand() << vtown[i].getErdteil() << endl;
   }

   cout << "Aktuelle Zahl an Eintraegen: ";
   cout << static_cast<int> (vtown.size()) << endl;
}


int main()
{
   
   int Auswahl = 0;

   vector<Town>vtown;
   vector<Town>sv1;

   datenEinlesen(vtown);

   while (Auswahl != 5)
   {
       cout << " Konsolenmenue: " << endl << endl;
       cout << " [1] Alle Städte sortiert nach Land und Namen ausgeben " << endl;
       cout << " [2] Alle Städte sortiert nach Land und Einwohnerzahl ausgeben " << endl;
       cout << " [3] Länder und Gesamteinwohnerzahl in Millionenstädten ausgeben " << endl;
       cout << " [4] Alle Städte sortiert nach Einwohnerzahl im Jahr 2050 ausgeben " << endl;
       cout << " [5] Programm beenden " << endl;
       cin >> Auswahl;

       switch (Auswahl)
       {
       case 1:
           //sv1 = sort1(vtown);
           //ausgabe(sv1);
           break;
       case 2:
           break;
       case 3:
           break;
       case 4:
           break;
       case 5:
           break;
       default:
           cout << "Falsche Eingabe...";
           break;
       }
   }
   system("pause");

   return 0;
}

Code:
TOWN. H DATEI:

#pragma once
#include <string>
#include <vector>

using namespace std;

class Town
{
private:
   string name;
   string einwohnerzahl;
   string land;
   string erdteil;

public:
   Town();
   Town(string, string, string, string);
   ~Town();

   //Setter

   void setName(string);
   void setEinwohnerzahl(string);
   void setLand(string);
   void setErdteil(string);

   //Getter

   string getName() const { return name; }
   string getEinwohnerzahl() const { return einwohnerzahl; }
   string getLand() const { return land; }
   string getErdteil() const { return erdteil; }

   friend ostream &operator<< (ostream &ostr, Town &t);
};


Code:
TOWN. CPP DATEI:

#include "Town.h"

using namespace std;

ostream &operator<< (ostream &ostr, Town &t)
{
   ostr << t.name << ";" << t.einwohnerzahl << ";" << t.land << ";" << t.erdteil << endl;
   return ostr;
}

Town::Town()
{

}

Town::Town(string sname, string seinwohner, string sland, string serdteil)
{
   name = sname;
   einwohnerzahl = seinwohner;
   land = sland;
   erdteil = serdteil;
}


void Town::setName(string sname)
{
   name = sname;
}

void Town::setEinwohnerzahl(string seinwohner)
{
   einwohnerzahl = seinwohner;
}

void Town::setLand(string sland)
{
   land = sland;
}

void Town::setErdteil(string serdteil)
{
   erdteil = serdteil;
}

Town::~Town()
{
}
 

cwriter

Erfahrenes Mitglied
Is 'n bisserl viel, oder?
/EDIT: Tönt ein bisschen falsch: Der angegebene Code lässt das Problem finden und ist nicht übermässig gross, allerdings war das Problem nicht gut lokalisiert. Ausgabe oder Zeilennummern, wo das Verhalten vom erwarteten abweicht, wären hilfreich (statt 10 Minuten Problemsuchen nur 1 Minute) gewesen.

Auch der Platz, der für die Datei vorgesehen ist, wird vom Compiler freigelassen
Verstehe ich nicht. Hast du die Datei mit einem Linkertool auseinandergenommen und die Symbole nicht gefunden?
Oder meinst du, dass das Programm deine Variablen nicht befüllt?

jedoch nur ein schwarzer bildschirm und keinerlei Ausgabe.
aber leider wird die Datei nicht ausgegeben, sondern nur, dass die Datei erfolgreich gelesen wurde.
Was denn nun?
Was wird denn ausgegeben (Genaue Ausgabe, direkt von der Commandline kopiert)?

void datenEinlesen(vector<Town>vtown)
Kompiliert das überhaupt? Da sollte ein Abstand zwischen Typ und Identifier sein...

cout << static_cast<int> (vtown.size()) << endl;
Warum castest du das?

Dein eigentliches Problem ist aber wahrscheinlich viel einfacher:
void datenEinlesen(vector<Town>vtown)
C++ ist pass-by-value.
C++:
vector<Town>vtown;
//...
datenEinlesen(vtown);
Damit kopierst du die Werte aus vtown (welches momentan leer ist) in den Scope der Funktion datenEinlesen.
Innerhalb der Funktion modifizierst du somit nur die Kopie (fügst Elemente an die Kopie an). Wenn die Funktion endet, werden die Parameter (also auch vtown) aufgeräumt (=gelöscht) und das Programm wechselt wieder in den Scope der main(), wo aber vtown noch immer leer ist.
Lösung:
C++:
void datenEinlesen(vector<Town>& vtown)
Das '&' erstellt eine Referenz (für C-Menschen: Glorifizierter Pointer), sodass das Argument pass-by-reference und nicht mehr pass-by-value ist.

Ob der Rest des Codes stimmt: Keine Ahnung. Frage nach, wenn sich etwas ergibt.

Gruss
cwriter
 

hawk2

Grünschnabel
Hallo cwriter,

vielen Dank für deine Zeit und Hilfe. Ich habe mal den Debugger gestartet und gemerkt, dass das Objekt '"ctown" nicht gefüllt wird <Error Reading characters of string>. Ich verstehe nur nicht, warum das Objekt nicht mit den Werten gefüllt wird :/

Code:
while (getline(f, zeile)) 
   {
       vector<string> columns = split(zeile, ';');
       Town ctown;

       ctown.getName() = columns[0];
       ctown.getEinwohnerzahl() = columns[1];
       ctown.getLand() = columns[2];
       ctown.getErdteil() = columns[3];

       vtown.push_back(ctown);
   }

Gruß
 

cwriter

Erfahrenes Mitglied
Ich verstehe nur nicht, warum das Objekt nicht mit den Werten gefüllt wird :/
Weil ein Getter halt kein Setter ist?

Der Getter (wie du es ja schon genannt hast) holt einen Wert.
Entweder kannst du beim Rückgabetyp auch ein & hinzufügen oder du nutzt dafür Setterfunktionen.
Das Prinzip ist hier dasselbe: Wieder hast du eine Kopie, die du veränderst.

Gruss
cwriter