Datei mit istream_iterator einlesen



  • Liebe Grüße an den "Professor", Fließkommazahlen sind nicht für Geldbeträge geeignet.



  • @Suprax sagte in Datei mit istream_iterator einlesen:

    Customer -> enthält Information mit der '#' Zeile ( Kundennr, vor- nachname, plz, stadt)

    Dein "Schema" ist absolut unvollständig.

    Wie werden die Strings denn unterschieden?
    123478 Walther der Vogelweise SW1A 1AA London an der Themse
    Wie erkennt dein Programm korrekt, was Kundennummer, Vor- und Nachname, PLZ und Stadt ist?



  • @wob Das Programm des "Professors" kann nur [Vorname] [Nachname], die PLZ ist ein Dingsti ohne Leerzeichen und die Stadt geht bis zum Zeilenende ^^



  • @Th69 sagte in Datei mit istream_iterator einlesen:

    Weißt du denn schon, wie man Daten mit einem itstream_iterator ausliest? Ansonsten mache dich mal mit den Memberfunktionen davon vertraut: istream_iterator.

    Da du als Template-Parameter string angegeben hast, wird damit automatisch alles bis zum nächsten Whitespace (Leerzeichen, Zeilenumbrauch, ...) eingelesen.
    Die Strings kannst du also dann direkt zuweisen und bei den Zahlenwerten kannst du dann stoi bzw. stod dafür benutzen.

    Ja, ich hatte zuvor allerdings leichtere Aufgaben, bei der keine Klassen benötigt wurden.

    Genau, der erste Whitespace findet bereits nach dem ersten "Wort" statt und da mein erstes Wort eine Zahlenreihe ist muss ich den string in einen int casten. Dafür bietet sich, wie du schon gesagt hast, stoi an.

    Eine Möglichkeit durch die Textdatei zu iterieren wäre ja z.B.:

    string s{};
    
    while ( file_it != eos ) {
    
    s = *file_it;
    file_it++;
    

    Durch die Inkrementierung wander ich ja string für string ab, richtig? Wie kann ich jedoch einzelne Fallunterscheidung für das casten innerhalb des Schleifendurchlaufs machen?

    @Swordfish sagte in Datei mit istream_iterator einlesen:

    Liebe Grüße an den "Professor", Fließkommazahlen sind nicht für Geldbeträge geeignet.

    Würde ich ausrichten, aber ich glaub mit dem Prof sich anzulegen kommt nie gut 😂

    @wob sagte in Datei mit istream_iterator einlesen:

    @Suprax sagte in Datei mit istream_iterator einlesen:

    Customer -> enthält Information mit der '#' Zeile ( Kundennr, vor- nachname, plz, stadt)

    Dein "Schema" ist absolut unvollständig.

    Wie werden die Strings denn unterschieden?
    123478 Walther der Vogelweise SW1A 1AA London an der Themse
    Wie erkennt dein Programm korrekt, was Kundennummer, Vor- und Nachname, PLZ und Stadt ist?

    Inwiefern sollen die String denn unterschieden werden?
    Die Strings werden ja nach einem bestimmten Ablauf aufgerufen.
    Mithilfe der Funktion

    friend ostream& operator<<(ostream& os, const Purchase& p) { return os << "Artikel: "<< p.name << "Preis pro Stk: " << p.unit_price << "Anzahl: " << p.count; }
    

    Die Funktion steckt im restlichen Quellcode, der hier nicht gepostet wurde.
    Sowie die Textdatei eingelesen wird, wird sie ja auch ausgegeben oder liege ich da falsch?

    @Swordfish sagte in Datei mit istream_iterator einlesen:

    @wob Das Programm des "Professors" kann nur [Vorname] [Nachname], die PLZ ist ein Dingsti ohne Leerzeichen und die Stadt geht bis zum Zeilenende ^^

    Ja genau.

    #725454 Schenker Rudolf DE-30159 Hannover
    Shirt 135.95 1
    Tie 89.59 1
    #987654 Orbison Roy US-TN37075 Hendersonville
    Mug 1.49 3
    T-Shirt 14.90 1
    

    Die " " beim Professor kannst du allerdings weglassen, da es tatsächlich die Vorgabe meines Professors ist.



  • @Suprax sagte in Datei mit istream_iterator einlesen:

    Die " " beim Professor kannst du allerdings weglassen, da es tatsächlich die Vorgabe meines Professors ist.

    Ich bezweifle auch nicht daß er sich allerernstes "Professor" nennt.



  • Benutze keine Schleife für die 3 Datensätze, sondern lese einfach die Daten nacheinander ein (jeweils mit ++file_it; dazwischen).
    Nur darum herum eine Schleife, um mehrere Datensätze einzulesen.



  • No-Bullshit Lösung:

    #include <limits>
    #include <cstdlib>
    #include <cctype>
    #include <vector>
    #include <string>
    #include <iterator>
    #include <fstream>
    #include <iostream>
    #include <iomanip>
    
    std::istream& skipws(std::istream &is)
    {
        while (is && std::isspace(is.peek()))
            is.get();
        return is;
    }
    
    class Customer
    {
        int id;
        std::string name;
        std::string surname;
        std::string zip;
        std::string city;
    
        friend
        std::ostream& operator<<(std::ostream &os, Customer const &customer)
        {
            return os << customer.id  << ' ' << customer.name << ' ' << customer.surname << ' '
                      << customer.zip << ' ' << customer.city;
        }
    
        friend
        std::istream& operator>>(std::istream &is, Customer &customer)
        {
            char indicator;
            if (!(is >> std::skipws >> indicator) || indicator != '#') {
                is.setstate(std::ios_base::failbit);
                return is;
            }
    
            Customer tmp;
            if ((is >> tmp.id >> tmp.name >> tmp.surname >> tmp.zip) && skipws(is) && std::getline(is, tmp.city))
                customer = tmp;
            return is;
        }
    };
    
    class Purchase
    {
        std::string designation;
        double price; // sic!!
        int amount;
    
        friend
        std::ostream& operator<<(std::ostream &os, Purchase const &purchase)
        {
            return os << purchase.designation << ' ' << std::fixed << std::setprecision(2)
                      << purchase.price << ' ' << purchase.amount;
        }
    
        friend
        std::istream& operator>>(std::istream &is, Purchase &purchase)
        {
            if (is.peek() == '#') {
                is.setstate(std::ios_base::failbit);
                return is;
            }
    
            Purchase tmp;
            if (is >> tmp.designation >> tmp.price >> tmp.amount) {
                purchase = tmp;
                is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            }
            return is;
        }
    };
    
    class Order
    {
        Customer customer;
        std::vector<Purchase> purchases;
    
        friend
        std::ostream& operator<<(std::ostream &os, Order const &order)
        {
            os << order.customer << '\n';
            for (auto const &purchase : order.purchases)
                os << purchase << '\n';
            return os;
        }
    
        friend
        std::istream& operator>>(std::istream &is, Order &order)
        {
            Order tmp;
            if (!(is >> tmp.customer))
                return is;
    
            for (Purchase purchase; is >> purchase; is.clear())
                tmp.purchases.push_back(purchase);
            order = tmp;
            is.clear();
            return is;
        }
    };
    
    int main()
    {
        auto const filename{ "foo.txt" };
        std::ifstream is{ filename };
        if (!is.is_open()) {
            std::cerr << "Couldn't open\"" << filename << "\" for reading :(\n\n";
            return EXIT_FAILURE;
        }
    
        std::vector<Order> orders{ std::istream_iterator<Order>{ is }, std::istream_iterator<Order>{} };
    
        std::cout << "Orders:\n";
        for (auto const &order : orders)
            std::cout << order << '\n';
    }
    

    Bei Fragen kannst Du ja fragen.



  • @Suprax sagte in Datei mit istream_iterator einlesen:

    Wie erkennt dein Programm korrekt, was Kundennummer, Vor- und Nachname, PLZ und Stadt ist?

    Inwiefern sollen die String denn unterschieden werden?

    Das musst du ja wissen bzw. dein Schema muss das definieren, wie da getrennt wird. Wenn du nur Whitespace als Trenner hast, dann

    • kann dein Programm keine Doppelnamen
    • kann dein Programm keine Postleitzahlen mit Leerzeichen (wie z.B. in GB üblich, "SW1A 1AA" ist die PLZ des Buckingham Palace; oder auch in NL üblich: unter "2513 AA" erreichst du ein paar Politiker...)
    • ...

    Gut, das soll für dieses Übungsbeispiel wohl alles ignoriert werden.



  • @Th69 sagte in Datei mit istream_iterator einlesen:

    Benutze keine Schleife für die 3 Datensätze, sondern lese einfach die Daten nacheinander ein (jeweils mit ++file_it; dazwischen).
    Nur darum herum eine Schleife, um mehrere Datensätze einzulesen.

    Danke, ich versuchs nochmal. Sollte ich nicht vorankommen melde ich mich nochmal hier



  • @wob sagte in Datei mit istream_iterator einlesen:

    @Suprax sagte in Datei mit istream_iterator einlesen:

    Wie erkennt dein Programm korrekt, was Kundennummer, Vor- und Nachname, PLZ und Stadt ist?

    Inwiefern sollen die String denn unterschieden werden?

    Das musst du ja wissen bzw. dein Schema muss das definieren, wie da getrennt wird. Wenn du nur Whitespace als Trenner hast, dann

    • kann dein Programm keine Doppelnamen
    • kann dein Programm keine Postleitzahlen mit Leerzeichen (wie z.B. in GB üblich, "SW1A 1AA" ist die PLZ des Buckingham Palace; oder auch in NL üblich: unter "2513 AA" erreichst du ein paar Politiker...)
    • ...

    Gut, das soll für dieses Übungsbeispiel wohl alles ignoriert werden.

    Sorry, ich hab deinen Beitrag völlig überlesen.
    Aber ja tatsächlich kann es für die Übung erstmal ignoriert werden, weil die Txt-Datei ja vorgegeben wurde.