.txt in struct mit array member einlesen



  • Hallo!

    Im Rahmen meines Studiums besuche ich eine Vorlesung in der wir Programmieren mit C++ lernen. Da dies mein erstes Semester ist, bin ich also noch ein blutiger Anfänger. Ich hänge nun an einer Hausaufgabe fest, in der es darum geht, per fstream Daten aus einer .txt in eine struct einzulesen.

    Zum besseren Verständnis, kopier ich euch mal die Aufgabenstellung, damit ich mein Problem besser beschreiben kann:

    Eine Sorte besteht aus maximal 5 Zutaten. Daraus ergibt sich folgende Struktur:

    struct schokolade
    {
    char name[20];
    int gewicht;
    int zutat_id[5];
    int menge_in_prozent[5];
    };

    Sind weniger als 5 Zutaten für eine bestimmte Sorte nötig, wird die ID der ersten, nicht belegten Zutat mit der Zahl -1 versehen. Zur Herstellung aller Schokoladensorten existieren sieben Zutaten.

    Lesen Sie die Zusammensetzung der Schokoladensorten aus der Datei schoki.txt ein. Die Datei ist nach folgendem Schema aufgebaut:

    zartbitter ← Name der Schokoladensorte
    100 ← Gewicht der Schokolade in Gramm
    2 ← Anzahl der Zutaten
    kakao 70 ← Name der Zutat und Anteil der Zutat am Gesamtgewicht in %
    zucker 30 ← Name der Zutat und Anteil der Zutat am Gesamtgewicht in %

    Beachten Sie, dass der Name der Zutat in eine ID umgewandelt werden muss und dass in der Datei schoki.txt genau drei Sorten Schokolade beschrieben sind..

    Die Zutaten zur Schokoladenherstellung besitzen folgende Daten:
    einen Namen und
    einen Preis pro 100 Gramm in Euro.
    Daraus ergibt sich folgende Struktur:

    struct zutat
    {
    char name[20];
    float preis_pro_100gramm;
    };

    Aus der Datei zutaten.txt lesen Sie alle zur Verfügung stehenden Zutaten und deren jeweiligen Preis ein. Die Reihenfolge der Zutaten in der Datei bestimmt die Identifikationsnummer (ID) einer Zutat: Die erste Zutat aus der Datei bekommt die ID 0, die Zweite eine 1 und so fort. Die ID kann also mit dem Feldindex einer Zutat in der Auflistung gleichgesetzt werden.

    Die .txt Dateien sehen so aus.

    schoki.txt:

    vollmilch_mandel
    100
    5
    kakao 34
    kakaobutter 10
    milchpulver 20
    zucker 28
    mandeln 8

    marzipan
    100
    3
    kakao 50
    zucker 25
    marzipan 25

    keksschoki
    100
    5
    kakao 40
    mandeln 7
    kakaobutter 8
    zucker 30
    keks 15

    zutaten.txt:

    mandeln 1.10
    marzipan 1.22
    milchpulver 0.6
    kakao 0.82
    kakaobutter 2.2
    keks 0.64
    zucker 0.14

    Das Einlesen der zutaten.txt läuft reibungslos. Jedoch habe ich Probleme mit dem Einlesen der anderen Datei. Vor allem, da in dem ersten struct zwei int arrays sind. Mein problem hier ist, dass ich die Namen der Zutaten in eine ID umwandeln soll, also 7 Zutaten von oben nach unten mit 0-6. Vllt könnt ihr mir helfen, wie ich es hinbekomme, dass es mir die schoki.txt ordentlich einliest und ich statt der Namen der Zutaten, welche für die jeweilige Sorte benötigt werden, eine ID einliest.

    Hier ist mein Stück Code, welches ich bisher habe.

    #include <iostream>
    #include <fstream>
    #include <string>
    using namespace std;
    
    struct schokolade               //struct für Schokolade
    {
        string name;
        int gewicht;
        int zutat_id[5];
        int menge_in_prozent[5];
    };
    
    struct zutat                    //struct für die Zutaten
    {
        string name;
        float preis_pro_gramm;
    };
    
    int main()
    {
        zutat feld[7];              //einlesen der Datei "zutaten.txt" mit 7 Einträgen
        int i = 0;
        ifstream file;
        file.open("zutaten.txt");
        if(file.is_open()){
    
            for(i; i<7; i++)
            {
    
                file >> feld[i].name;
                file >> feld[i].preis_pro_gramm;
            }
    
            file.close();
        }
        else{
            cout << "Datei Konnte nicht geöffnet werden!" << endl;
            return 0;
        }
    
        schokolade feld_2[3];
        int j=0;
        int k=0;
        for(j; j<3; j++)
        {
            for(int i=0; i<5; i++)
            {
    
            feld_2[j].zutat_id[i] = i;      //Vergeben einer ID für die jeweilige Zutat
            }
        }
    
        ifstream file_2;                    //Einlesen der Datei "schoki.txt" mit 3 Einträgen
        file.open("schoki.txt");
        if(file.is_open()){
    
            file_2 >> feld_2[j].name;
            file_2 >> feld_2[j].gewicht;
            file_2 >> feld_2[j].menge_in_prozent[5];
        }
        file_2.close();
    
        for(int i=0; i<7; i++)  //ab hier nur zur Veranschaulichung, ob es die Daten ordentlich einliest
        {
            cout << "Name: " << feld[i].name <<" Preis pro Gramm: " << feld[i].preis_pro_gramm << "\n";
        }
        for(int j=0; j<3; j++)
        {
            for (int i=0; i<7; i++)
            {
                cout << "Name: " << feld_2[j].name <<" Gewicht: " << feld_2[j].gewicht << "ID: " << feld_2[j].zutat_id[i] <<" Menge in Prozent: " << feld_2[j].menge_in_prozent << "\n";
            }
        }
        return 0;
    }
    

    Sry für die Wall of Text, aber ich weiß leider nicht wie ich das Problem besser beschreiben soll 😞 😞 😞



  • wie wäre es, wenn du die Zutaten in ein string array packst und als ID die indices nimmst? Bei sehr vielen Zutaten würde sich wohl auch eine map eignen (Zutat = Key, ID = Value).



  • Atrom schrieb:

    Vllt könnt ihr mir helfen, wie ich es hinbekomme, dass es mir die schoki.txt ordentlich einliest und ich statt der Namen der Zutaten, welche für die jeweilige Sorte benötigt werden, eine ID einliest.

    Hallo,

    das kannst du sicherlich auch selber:

    size_t nameToIndex(const std::string& name)  // ggf. array mit übergeben
    {
    ...
    }
    ...
    size_t index = nameToIndex(readName);
    

    ps: Code-Vorgabe sieht schrottig aus. Nach dem Kurs unbedingt ein gutes Buch lesen, damit sich der Mist nicht verfestigt.



  • Danke erstmal für den Tipp. Ja, dass das schrottig aussieht, mag sein...aber anders wird es uns auch nicht gezeigt.



  • Zum Problem selber: Variablen sollten immer so lokal wie möglich sein, das zeigt sich in deinem bei j und file/file_2. Wenn du keine Funktionen verwenden möchtest, kannst du auch Scopes einfügen.

    for(j; j<3; j++) // so lokal wie möglich, also int j=0;.., schlecht: nackte Zahlen wie auch 5&7, etwas besser wäre es, Konstanten zu verwenden
        {
            for(int i=0; i<5; i++) // richtig, hier undurchsichtig, da dieses i Darüberleigendes überdeckt 
            {
    
            feld_2[j].zutat_id[i] = i;      //Vergeben einer ID für die jeweilige Zutat
            }
        }
    
    //  ifstream file_2("schoki.txt") <- besser direkt so
        ifstream file_2;                    //Einlesen der Datei "schoki.txt" mit 3 Einträgen
    
        file.open("schoki.txt"); // schlecht: sollte wohl file_2 sein
        if(file.is_open()){ //
    
            file_2 >> feld_2[j].name; // s.o., hier das resultierende Problem mit dem stream und auch j, j ist hier 3, der Code sollte wohl in einer Schleife stehen
            file_2 >> feld_2[j].gewicht;
            file_2 >> feld_2[j].menge_in_prozent[5];
        }
    

    Das ist nur, was mir direkt ins Auge gesprungen ist.



  • Atrom schrieb:

    Danke erstmal für den Tipp. Ja, dass das schrottig aussieht, mag sein...aber anders wird es uns auch nicht gezeigt.

    Ich weiss, deshalb ja auch 'Code-Vorlage' (gemeint war die der Aufgabe).



  • dref schrieb:

    Zum Problem selber: Variablen sollten immer so lokal wie möglich sein, das zeigt sich in deinem bei j und file/file_2. Wenn du keine Funktionen verwenden möchtest, kannst du auch Scopes einfügen.

    for(j; j<3; j++) // so lokal wie möglich, also int j=0;.., schlecht: nackte Zahlen wie auch 5&7, etwas besser wäre es, Konstanten zu verwenden
        {
            for(int i=0; i<5; i++) // richtig, hier undurchsichtig, da dieses i Darüberleigendes überdeckt 
            {
     
            feld_2[j].zutat_id[i] = i;      //Vergeben einer ID für die jeweilige Zutat
            }
        }
     
    //  ifstream file_2("schoki.txt") <- besser direkt so
        ifstream file_2;                    //Einlesen der Datei "schoki.txt" mit 3 Einträgen
    
        file.open("schoki.txt"); // schlecht: sollte wohl file_2 sein
        if(file.is_open()){ //
     
            file_2 >> feld_2[j].name; // s.o., hier das resultierende Problem mit dem stream und auch j, j ist hier 3, der Code sollte wohl in einer Schleife stehen
            file_2 >> feld_2[j].gewicht;
            file_2 >> feld_2[j].menge_in_prozent[5];
        }
    

    Das ist nur, was mir direkt ins Auge gesprungen ist.

    Danke! Habe ich gleich mal ausgebessert!

    Das Problem ist halt, dass das mit dem fstream nur mal 10min angeschnitten wurde , an einem sehr simplen Beispiel und dieses "nametoindex" war mir gar nicht bekannt.



  • Atrom schrieb:

    und dieses "nametoindex" war mir gar nicht bekannt.

    Das gibt es ja auch nicht. Das solltest du selber machen.
    Hab nur die Signatur als Denkansatz geliefert - der Rest schreibt sich ja dann fast alleine.



  • Du hast die Zutaten doch bereits in ein Array eingelesen. Der Index dieses Array entspricht genau der gesuchten ID.

    Jetzt brauchst du beim Einlesen der Schokolade nur jeweils in einer Schleife das Zutatenarray von Anfang an durchzugehen bis der name der Zutat dem Namen in "feld.name" entspricht (blöder Name übrigens, besser wäre z.B. zutatenliste). Den entsprechenden Index nimmst du dann als Id für die Schokolade.



  • Also danke für eure Hilfe Leute, ich habe es jetzt hinbekommen! 🙂 👍



  • Hallo
    ich hab die selbe aufgabe :p
    und ich weiß auch nicht wie ich die Daten aus der schoki.txt auslese



  • Das Auslesen funktioniert genauso, wie bei der Datei "zutaten.txt". Steht doch schon da...


Anmelden zum Antworten