.txt Datei einlesen und in Vectoren speichern



  • Dieser Beitrag wurde gelöscht!


  • Der Ansatz ist schon ganz richtig, nur dürfen die Variablen iata, airport ... und so weiter die du in der Funktion AusDateiLesen() als lokale Varablen definiert hast, keine lokalen Variablen sein, denn sonst sind die ja mit verlassen der Funktion AusDateiLesen() wieder weg. Diese musst du in den Header der Klasse Airport übernehmen und auch nur diese dann "befüllen". Schlussendlich arbeitet das die Klasse Airport nur mit den paar Variablen.

    Beispiel weil es einfacher ist als das ganze zu erklären:

    class Airport
    {
        Airport(string zeile)
        {
            stringstream zeilenpuffer(zeile);
    		zeilenpuffer >> iata >> airport >> city >> stateAbbreviation >> country >> breite >> laenge;
        };
        
    protected:
    	string iata;
    	string airport;
    	string city;
    	string stateAbbreviation;
    	string country;
    	double breite;
    	double laenge;
    };
    class Flughaefen 
    {
        ReadCSV(string Path)
        {
            ifstream AirportDatei("airports.txt", ios::in);
            string zeile;
        	while (getline(AirportDatei, zeile))
        	{
        		for (int i = 0; i < zeile.size(); i++)
        		{
        			if (zeile[i] == ',')
        			{
        				zeile[i] = ' ';
        			}
        		}
                Airport AP(zeile);
                Airports.pushback(AP);
        	}
        };
    protected:
        vector<Airport> Airports;
    };
    

    So mal als Beispiel, ich kann dir noch nciht mal sagen ob ich da Fehler drin habe, ich hab das so micht getestet. Es soll ja nur veranschaulichen wie ich das ganze erstellen würde.

    Wenn du dann konsequent die Hirarchie einhällst dann brauchst du nur eine Funktion in Flughäfen zu integrieren und diese ruft dann einfach nur wiederum Funktionen der Klasse Airport auf in dem du einfach den vector durchläufst und für jeden Airport die entstrechende Funktion auf rufst, also zum beispiel ein vergleich ob das der gesuchte Flughafen ist.



  • Dieser Beitrag wurde gelöscht!


  • #include <limits>
    #include <cstdlib>
    #include <iterator>
    #include <vector>
    #include <string>
    #include <fstream>
    #include <iostream>
    #include <algorithm>
    
    class airport_t
    {
    	std::string iata;
    	std::string name;
    	std::string city;
    	std::string state;
    	std::string country;
    	double latitude   = std::numeric_limits<double>::quiet_NaN();
    	double longitude  = std::numeric_limits<double>::quiet_NaN();
    
    public:
    	airport_t() = default;
    	airport_t(std::string iata, std::string name, std::string city, std::string state, std::string country, double latitude, double longitude)
    	: iata       { iata      },
    	  name       { name      },
    	  city       { city      },
    	  state      { state     },
    	  country    { country   },
    	  latitude   { latitude  },
    	  longitude  { longitude }
    	{}
    
    	friend
    	std::istream& operator>>(std::istream &is, airport_t &airport)
    	{
    		airport_t temp;
    		std::string latitude;
    		std::string longitude;
    
    		if (!(std::getline(is, temp.iata, ',') && std::getline(is, temp.name, ',') && std::getline(is, temp.city, ',') &&
    		      std::getline(is, temp.state, ',') && std::getline(is, temp.country, ',') && std::getline(is, latitude, ',') &&
    		      std::getline(is, longitude)))
    		{
    			return is;
    		}
    
    		try {
    			temp.latitude   = std::stod(latitude);
    			temp.longitude  = std::stod(longitude);
    		}
    		catch (...) {
    			is.setf(std::ios::failbit);
    			return is;
    		}
    
    		airport = temp;
    		return is;
    	}
    
    	friend
    	std::ostream& operator<<(std::ostream &os, airport_t const &airport)
    	{
    		return os << airport.iata << ", " << airport.name << ", " << airport.city << ", " << airport.state << ", "
    		          << airport.country << ", " << airport.latitude << ", " << airport.longitude;
    	}
    };
    
    int main()
    {
    	char const *input_filename { "airports.txt" };
    	std::ifstream input_file   { input_filename };
    
    	if (!input_file.is_open()) {
    		std::cerr << "Couldn't open \"" << input_filename << "\" for reading :(\n\n";
    		return EXIT_FAILURE;
    	}
    
    	// discard first line:
    	input_file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    	
    	// read:
    	std::vector<airport_t> airports { std::istream_iterator<airport_t>{ input_file }, std::istream_iterator<airport_t>{} };
    
    	// write:
    	std::copy(airports.begin(), airports.end(), std::ostream_iterator<airport_t>{ std::cout, "\n" });
    }
    

    Um die Anführungszeichen musst Du Dich selbst kümmern.



  • @Swordfish Wow vielen dank dafür.
    Das kann ich ja ohne viel Aufwand auch für andere Aufgaben dieser Art verwenden, natürlich Variablen ändern und gucken ob anstatt Kommata, Punkte oder Tabs verwendet wurden. Vielen dank an alle, hab das ganze jetzt denke ich gut genug Verstanden^^



  • @Swordfish

    Habe das ganze jetzt getestet, funktioniert super. Allerdings habe ich 2 fragen dazu.

    1. ist das write dafür gedacht um wieder in ein Textdokument zu schreiben?
    2. Scheinbar wird jede Zeile aus dem Dokument 6 mal eingelesen. Zumindest wenn ich es mir mithilfe einer for() schleife ausgeben lasse.

  • Mod

    @Deaster sagte in .txt Datei einlesen und in Vectoren speichern:

    @Swordfish

    Habe das ganze jetzt getestet, funktioniert super. Allerdings habe ich 2 fragen dazu.

    1. ist das write dafür gedacht um wieder in ein Textdokument zu schreiben?

    Es gibt nach cout aus , wo auch immer das ist (meistens ein Textterminal, aber es kann potentiell auch eine Datei sein). Ich dachte, du hättest das Programm ausprobiert? Da sieht man das doch.

    1. Scheinbar wird jede Zeile aus dem Dokument 6 mal eingelesen. Zumindest wenn ich es mir mithilfe einer for() schleife ausgeben lasse.

    Das ist aber nur scheinbar. Wie genau denkst du denn, das festgestellt zu haben? Dein Fehler ist wohl eher in deiner Methode, mit der du dies festgestellt zu haben glaubst. Das "write" von Swordfish ist nämlich auch nur eine verkappte Schleife und gibt hoffentlich das richtige aus.



  • @SeppJ Da das write von Swordfish einige Fehler anzeigte hatte ich es selbst mit einer simplen for() schleife ausgeben lassen.

    Main:

    copy(airports.begin(), airports.end(), ostream_iterator<Airport>{cout, '\n'});
    

    Airport.h:

    friend ostream& operator<<(ostream &os, Airport const &airport)
    	{
    		return os << airport.iata << "," << airport.name << "," << airport.city << "," << airport.stateAbbreviation << "," << airport.country << "," << airport.breite << "," << airport.laenge;
    	}
    

    Fehlermeldungen:
    Keine Instanz des Konstruktors ""std::ostream_iterator<_Ty, _Elem, _Traits>::ostream_iterator [mit _Ty=Airport, _Elem=char, _Traits=std::char_traits<char>]"" stimmt mit der Argumentliste überein.

    "Initialisierung": "initializer list" kann nicht in "std::ostream_iterator<Airport,char,std::char_traits<char>>" konvertiert werden

    "copy": keine übereinstimmende überladene Funktion gefunden

    Sorry falls ich manchmal etwas sehr auf dem Schlauch stehe..
    Vielen dank für eure Mühe

    "_DestTy *std::copy(_InIt,_InIt,_DestTy (&)[_DestSize])": Erwartet 3 Argumente - 2 unterstützt

    "_OutIt std::copy(_InIt,_InIt,_OutIt)": Erwartet 3 Argumente - 2 unterstützt

    Sorry falls ich manchmal etwas sehr auf dem Schlauch stehe.
    Vielen dank für eure Mühe 🙂



  • Wenn du noch nicht einmal vernünftig den Code kopieren kannst?

    // write:
    std::copy(airports.begin(), airports.end(), std::ostream_iterator<airport_t>{ std::cout, "\n" });
    

    vs.

    copy(airports.begin(), airports.end(), ostream_iterator<Airport>{cout, '\n'});
    

    (und ich meine nicht die fehlenden std:: oder den anderen Klassennamen...)

    Ansonsten schau in die Referenz: std::ostream_iterator<T,CharT,Traits>::ostream_iterator



  • @Deaster Meine Zeile mit std::copy<>() nochmal gaaaanz genau lesen. Insbesondere die Argumente des Konstructors vom std::ostream_iterator<>.



  • Ja ok das war sehr dämlich von mir.
    Das Ursprüngliche Problem bleibt allerdings bestehen. Jede Zeile wird 6 fach ausgegeben.



  • @Deaster Dann poste Deine Eingabedatei und ein kompilierbares Minimalbeispiel, die erwartete Ausgabe und die tatsächliche.



  • Ok verzeihung, hab den Fehler gefunden... Hatte ein Tippfehler gehabt. 🤦🏻♂
    Bin euch extrem dankbar für eure Mühe 🙂



  • Spaßeshalber:

    #include <limits>
    #include <cstdlib>
    #include <cctype>
    #include <iterator>
    #include <vector>
    #include <string>
    #include <fstream>
    #include <iostream>
    #include <algorithm>
    
    
    // Following functions trim string str up to and including one of the characters in delims.
    // If delims is a zero length string, they trim up to the first none whitespace character:
    
    void trim_left(std::string &str, std::string const &delims = "")
    {
    	str.erase(str.begin(), std::find_if_not(str.cbegin(), str.cend(), [](int ch) { return std::isspace(ch); }));
    	
    	if (str.length() && delims.length() && delims.find(str.front()) != delims.npos)
    		str.erase(0, 1);
    }
    
    void trim_right(std::string &str, std::string const &delims = "")
    {
    	str.erase(std::find_if_not(str.crbegin(), str.crend(), [](int ch) { return std::isspace(ch); }).base(), str.end());
    
    	if (str.length() && delims.length() && delims.find(str.back()) != delims.npos)
    		str.pop_back();
    }
    
    void trim(std::string &str, std::string const &delims = "")
    {
    	trim_left(str, delims);
    	trim_right(str, delims);
    }
    
    // Encloses a string in quotation marks
    std::string quote(std::string str, bool quoted = true, char quotation_mark = '"')
    {
    	if (!quoted)
    		return str;
    
    	return std::string{ quotation_mark } + str + quotation_mark;
    }
    
    
    class airport_t
    {
    	static char constexpr delim = ',';
    	static char constexpr quotation_mark = '"';
    	static int quoted_flag_index;
    	
    	enum quoted_t { unquoted_output, quoted_output };
    
    	std::string iata;
    	std::string name;
    	std::string city;
    	std::string state;
    	std::string country;
    	double latitude   = std::numeric_limits<double>::quiet_NaN();
    	double longitude  = std::numeric_limits<double>::quiet_NaN();
    
    public:
    	airport_t() = default;
    	airport_t(std::string iata, std::string name, std::string city, std::string state, std::string country, double latitude, double longitude)
    	: iata       { iata      },
    	  name       { name      },
    	  city       { city      },
    	  state      { state     },
    	  country    { country   },
    	  latitude   { latitude  },
    	  longitude  { longitude }
    	{}
    
    	
    	// Stream extraction and insertion:
    	
    	friend
    	std::istream& operator>>(std::istream &is, airport_t &airport)
    	{
    		airport_t temp;
    		std::string latitude;
    		std::string longitude;
    
    		if (!(std::getline(is, temp.iata, delim) && std::getline(is, temp.name, delim) && std::getline(is, temp.city, delim) &&
    		      std::getline(is, temp.state, delim)  && std::getline(is, temp.country, delim) && std::getline(is, latitude, delim) &&
    		      std::getline(is, longitude)))
    		{
    			return is;
    		}
    
    		try {
    			temp.latitude   = std::stod(latitude);
    			temp.longitude  = std::stod(longitude);
    		}
    		catch (...) {
    			is.setf(std::ios::failbit);
    			return is;
    		}
    		
    		std::string const quotation_mark_str { quotation_mark };
    		trim(temp.iata,    quotation_mark_str);
    		trim(temp.name,    quotation_mark_str);
    		trim(temp.city,    quotation_mark_str);
    		trim(temp.state,   quotation_mark_str);
    		trim(temp.country, quotation_mark_str);
    
    		airport = temp;
    		return is;
    	}
    
    	friend
    	std::ostream &operator<<(std::ostream &os, airport_t const &airport)
    	{
    		bool const quoted { os.iword(quoted_flag_index) == quoted_output };
    
    		return os << quote(airport.iata, quoted, quotation_mark) << ", " << quote(airport.name,  quoted, quotation_mark) << ", "
    		          << quote(airport.city, quoted, quotation_mark) << ", " << quote(airport.state, quoted, quotation_mark) << ", "
    		          << quote(airport.country, quoted, quotation_mark) << ", " << airport.latitude << ", " << airport.longitude;
    	}
    
    	// Stream manipulators:
    	friend std::ios_base &quoted(std::ios_base&);
    	friend std::ios_base &unquoted(std::ios_base&);
    };
    
    int airport_t::quoted_flag_index = std::ios_base::xalloc();
    
    
    // Stream manipulators:
    
    std::ios_base &quoted(std::ios_base &os)
    {
    	os.iword(airport_t::quoted_flag_index) = airport_t::quoted_output;
    	return os;
    }
    
    std::ios_base &unquoted(std::ios_base &os)
    {
    	os.iword(airport_t::quoted_flag_index) = airport_t::unquoted_output;
    	return os;
    }
    
    
    int main()
    {
    	char const *input_filename{ "airports.txt" };
    	std::ifstream input_file{ input_filename };
    
    	if (!input_file.is_open()) {
    		std::cerr << "Couldn't open \"" << input_filename << "\" for reading :(\n\n";
    		return EXIT_FAILURE;
    	}
    
    	// discard first line:
    	input_file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    
    	// read:
    	std::vector<airport_t> airports{ std::istream_iterator<airport_t>{ input_file }, std::istream_iterator<airport_t>{} };
    
    	// write:
    	std::copy(airports.begin(), airports.end(), std::ostream_iterator<airport_t>{ std::cout, "\n" });
    	std::cout.put('\n');
    
    	// write with quotes:
    	std::cout << quoted;
    	std::copy(airports.begin(), airports.end(), std::ostream_iterator<airport_t>{ std::cout, "\n" });
    	std::cout.put('\n');
    
    	// write without quotes again:
    	std::cout << unquoted;
    	std::copy(airports.begin(), airports.end(), std::ostream_iterator<airport_t>{ std::cout, "\n" });
    	std::cout.put('\n');
    }
    

    airports.txt:

    "iata","airport","city","stateAbbreviation","country","lat","long"
    "00M",          	"Thigpen","Bay Springs","MS","USA"       ,31.95376472,-89.23450472
    "35CA","Los Angeles County/USC Medical Center Heliport"	,"Los Angeles","CA","USA",-118.208056,34.0575
    "FRA","San Francisco Airport"	,	"San Francisco","CA","USA",-62.1336, -31.4142
    

    Output:

    00M, Thigpen, Bay Springs, MS, USA, 31.9538, -89.2345
    35CA, Los Angeles County/USC Medical Center Heliport, Los Angeles, CA, USA, -118.208, 34.0575
    FRA, San Francisco Airport, San Francisco, CA, USA, -62.1336, -31.4142
    
    "00M", "Thigpen", "Bay Springs", "MS", "USA", 31.9538, -89.2345
    "35CA", "Los Angeles County/USC Medical Center Heliport", "Los Angeles", "CA", "USA", -118.208, 34.0575
    "FRA", "San Francisco Airport", "San Francisco", "CA", "USA", -62.1336, -31.4142
    
    00M, Thigpen, Bay Springs, MS, USA, 31.9538, -89.2345
    35CA, Los Angeles County/USC Medical Center Heliport, Los Angeles, CA, USA, -118.208, 34.0575
    FRA, San Francisco Airport, San Francisco, CA, USA, -62.1336, -31.4142
    

Anmelden zum Antworten