Zeilenweises auslesen aus einer Text-Datei



  • Hi,
    ich bin jetzt auf eine recht einfache Idee gekommen eine bestimmte Zeile aus
    einer Textdatei einzulesen, was haltet ihr davon?(Knudellbaer sagte ich solle Vektoren benutzen, aber mit denen kenne ich mich halt nicht aus)

    Ich lasse eine Schleife durchlaufen, deren Zähler jedesmal inkrementiert wird, wenn sie durchläuft und lese dann eine Zeile ein, die immer den Inhalt des vorherigen strings überschreibt, wenn Zähler und Zeilennummer gleich sind endet die Schleife.

    #include <conio.h>
    
    //STL Headers:
    #include <iostream>
    #include <string>
    #include <fstream>
    using namespace std;
    
    class Stream{
    
    private:
    ifstream Data;
    
    protected:
    //Das ist der rückgabewert in dem der Inhalt der Datei ist
    string content;
    
    public:
    
    /* In den Parametern wird der Programmpfad sowie die Zeilennummer die für die Schleife notwendig sind 
    ausgelagert*/
    string ReadLine(char Path[],int NumberOfLine){
    
             Data.open(Path);
    
             string content;
    
             int i;
             for(i=0;i<NumberOfLine;i++)//Schleife die Jedesmal wenn sie durchläuft eine 
             //Zeile weiter unten einliest
             {
             getline(Data,content);
             }
    
             Data.close();
    
    //rückgabe des Werts, der in dem String ReadLineValue gespeichert wird
    return content;
    };
    
    };
    
    //MainFunction
    int main()
    {
    //String für den Rückgabewert
    string ReadLineValue;
           ReadLineValue=Stream().ReadLine("VokabelnDeutsch.txt",10);
    cout <<ReadLineValue;
    
    getch();
    };
    


  • Was hältst du hiervon:

    vector<string> lines;
    ifstream file("foo.txt");
    string buffer;
    while(getline(file, buffer))
      lines.push_back(buffer);
    
    //gib 10. Zeile aus:
    cout<<lines[9];
    
    //gib n. Zeile aus:
    cout<<lines[n-1];
    

    ich finde das einfacher...

    es kommt aber auf die größe der Datei an.
    Deine Methode gefällt mir nicht so gut, da die Festplatte leider recht langsam ist, würde ich einfach alles in den RAM mappen und dort damit arbeiten...



  • Hi,
    vielen dank.

    Shade Of Mine schrieb:

    es kommt aber auf die größe der Datei an.

    Das ganze soll ein Vokabeltrainer werden(ist schon recht fertig 😃 ), im moment sind es
    rund 500 Vokabeln. Ich ermittle also eine Zufallszahl und lese dann
    diese Zeile ein.

    Shade Of Mine schrieb:

    Deine Methode gefällt mir nicht so gut, da die Festplatte leider recht langsam ist, würde ich einfach alles in den RAM mappen und dort damit arbeiten...

    Ich werde mal schauen das ich heute abend noch den Zufallsgenerator hinbekomme und es dann auf einem 400 Mhz Rechner testen. Wenn es dort einigermaßen flüssig läuft, werde ich bei meiner Methode bleiben, da ich deine nicht wirklich verstehe. (Kommt morgen Buch :xmas1: , kommt rat 😉 )

    trotzallem vielen dank.

    cu max



  • flüssig läuft es wahrscheinlich auch mit deiner methode.

    aber meine hat den vorteil, dass du einmal beim starten alles einliest. zB 70000 Vokabeln - und nicht jedesmal alle zeilen einliest und sie wegschmeisst...

    es wird zwar auch auf deine art funktionieren - aber mir persönlich tut es weh, wenn man rechnzeit so vergeudet...



  • Hi,
    natürlich hast du recht, das es völlig verschwenderisch ist.
    Ich benutze nur sehr ungern Code den ich nicht verstehe,
    deshalb benutze ich im moment meinen. Wenn ich etwas fortgeschrittener bin,
    ist deine mölichkeit natürlich die richtige lösung und ich werde sie verwenden.

    Vielen dank.

    cu max



  • Hi,
    ich knüpfe jetzt einfach an den Thread von oben an.(Da die Klasse zum einlesen aus der Datei ja schon oben steht.)

    Also ich habe nun einen Zufallsgenerator(Danke Knuddelbaer 😉 )
    dessen aufruf in einer do while Schleife steht:

    class Random{
    
    private:
    int RandomValue;
    
    public:
    
    int m_RandomValueFunction(int MaxValueOfZeichen){/*Hier übergebe ich die Zahl 353 an MaxValueOfZeichen*/
    
    srand((unsigned)time( NULL ));
    
    RandomValue=rand()%MaxValueOfZeichen;
    
    return RandomValue;
    
    }
    
    };
    

    Dieser gibt einen Wert zurück der dann an das Zeilen auslesen übergeben wird, damit die Richtige Zeile ausgelesen wird. Nun gut ich habe zwei Probleme:
    -Der Zufallsgenerator spuckt oft gleiche Zahlen aus, aber auch manchmal welche die noch nie dran waren //liegt das an der Schleife?
    -Viele wörter haben nach dem auslesen aus der Datei komische Zeichen 🙄 , deshalb bekomme ich dann auch oft Fehler bei dem Vergleich mit dem eingelesenen(cin).//es funktioniert aber auch manchmal

    Vielen dank im voraus.

    cu max



  • dann schau doch mal in die FAQ.

    btw: warum verwendest du Klassen wo es eine funktion auch tun würde?

    zB statt Stream().ReadLine()
    kannst du doch eine Funktion ReadLine() schreiben...
    das wäre viel sauberer.

    es sei denn Stream würde irgendwelche Daten speichern, was es aber (momentan) nicht tut.

    Detto beim Random

    Der 'Trick' ist: srand() wird nur einmal initialisiert:

    int getRandomNumber(int max)
    {
      static bool srandCalled=false;
      if(!srandCalled)
      {
        srand(static_cast<unsigned>(time(0));
        srandCalled=true;
      }
      return rand()%max;
    }
    


  • Hi,

    Shade Of Mine schrieb:

    dann schau doch mal in die FAQ.

    In der Konsolen FAQ habe ich nichts gefunden.
    http://www.c-plusplus.net/forum/viewtopic.php?t=39326 //das hat ja nur etwas mit der Anzeige zu tuen, nicht mit dem Vergleich, der ja eigentlich immer davor funktioniert hat. Und im moment ist nur der Vergleich wichtig, nicht die optik, die will ich eh irgedwann mit der WinAPI machen.

    Shade Of Mine schrieb:

    btw: warum verwendest du Klassen wo es eine funktion auch tun würde

    Hmmm, ich habe es mir irgendwie angewohnt, ich finde es komfortabler
    (es bringt ja auch keine nachteile mit sich)

    Shade Of Mine schrieb:

    zB statt Stream().ReadLine()
    kannst du doch eine Funktion ReadLine() schreiben...
    das wäre viel sauberer.

    es sei denn Stream würde irgendwelche Daten speichern, was es aber (momentan) nicht tut.

    Der Stream wird auch noch falsche Vokabeln in Textdateien abspeichern.
    Man soll dan auswählen können ob man die Falschen Vokabeln abfragen will oder irgedwelche zufällige. Wenn die Vokabel richtig ist lösche ich sie wieder aus der Textdatei.

    Der 'Trick' ist: srand() wird nur einmal initialisiert

    Danke super, damit dürfte es richtig laufen 😃

    [EDIT]Wegen dem speed ist die einlese methode nun inline, dürfte noch ne menge Speed bringen[EDIT]

    Vielen dank.

    cu max



  • Master_Max schrieb:

    In der Konsolen FAQ habe ich nichts gefunden.

    schau halt in de ANSI C oder C++ FAQ...

    Hmmm, ich habe es mir irgendwie angewohnt, ich finde es komfortabler
    (es bringt ja auch keine nachteile mit sich)

    Naja, der Code wird unübersichtlicher und verwirrender.
    In C++ verwendet man gerne Funktionen - was du machst ist eher Java...

    [EDIT]Wegen dem speed ist die einlese methode nun inline, dürfte noch ne menge Speed bringen[EDIT]

    Ne, inlinen tut sowieso der Compiler. Und selbst wenn - function calls sind so billig geworden, damit reisst du nix mehr...



  • Hi,

    Shade Of Mine schrieb:

    schau halt in de ANSI C oder C++ FAQ...

    Werde ich tuen.

    Shade Of Mine schrieb:

    was du machst ist eher Java...

    "Weiche Java, weiche!", Java will ich nicht machen. Ich dachte
    es heißt C with Classes, deshalb habe ich es übertrieben.

    Shade Of Mine schrieb:

    Ne, inlinen tut sowieso der Compiler. Und selbst wenn - function calls sind so billig geworden, damit reisst du nix mehr...

    😞

    Naja ich denke ich weis jetzt woran es liegt, es sind Französische Vokabeln also lauter é à ... daran wird es wohl liegen.

    Der Zufallsgenerator funktioniert prächitig.
    Vielen dank.

    cu max



  • Master_Max schrieb:

    "Weiche Java, weiche!", Java will ich nicht machen. Ich dachte
    es heißt C with Classes, deshalb habe ich es übertrieben.

    Java ist doch nix böses 😕

    C++ hat den Vorteil, dass du Funktionen verwenden kannst, wo es Sinn macht.
    zB getRandomNumber() ist eine super Funktion... Ich wüsste nicht, was es in einer Klasse verloren hätte...

    Naja ich denke ich weis jetzt woran es liegt, es sind Französische Vokabeln also lauter é à ... daran wird es wohl liegen.

    was meinst du damit?

    es ist getline() egal was für Zeichen es einliest. Schließlich ist ein é ja auch nur 1 Byte... bzw. 2 Byte falls wir von Unicode reden...



  • Hi,
    danke vielmals.

    Shade Of Mine schrieb:

    Java ist doch nix böses

    Ich habe mir mal ein Buch darüber besorgt und war nicht begeistert,
    kann aber auch an dem Buch liegen.

    Shade Of Mine schrieb:

    was meinst du damit?

    es ist getline() egal was für Zeichen es einliest. Schließlich ist ein é ja auch nur 1 Byte... bzw. 2 Byte falls wir von Unicode reden...

    OK, es ist Getline egal, aber dan muss es an meinem Vergleich des eingelesenen und eigegbenen liegen:
    (vereinfacht und ungetestet)

    int main(){
    
    string ReadLineValue; 
           ReadLineValue=Stream().ReadLine("VokabelnDeutsch.txt",Random); 
    cout <<ReadLineValue;//Deutsche Ausgabe
    
    string ReadLineLanguage; 
           ReadLineLanguage=Stream().ReadLine("VokabelnFrench.txt",Random); 
    
    string InVoc;
    cin >> InVoc;
    
    if(InVoc==ReadLineLanguage){
    cout << "richtig"<<endl<<endl;
    }
    else{
    cout << "wrong"<<endl<<endl;
    }
    
    }
    

    Aber das müsste stimmen, ich vergleiche ja einfach zwei strings.

    Hat jemand noch eine Idee woran es liegen könnte?

    cu max



  • liegt es uU an einem \n als letztes Zeichen im string?

    und vorallem: was machst du bei zB
    satisfy und als Antwort müsste dann ja gelten 'zufriedenstellen', 'befriedigen',...

    wie löst du dieses Problem?



  • Hi,

    Shade Of Mine schrieb:

    liegt es uU an einem \n als letztes Zeichen im string?

    Ich dachte das dies nur für char arrays gilt.

    Shade Of Mine schrieb:

    und vorallem: was machst du bei zB
    satisfy und als Antwort müsste dann ja gelten 'zufriedenstellen', 'befriedigen',...

    wie löst du dieses Problem?

    Sorry, ich verstehe deine Frage nicht.
    Du musst wissen das ich sehr neu in C++ bin und mich noch nicht wirklich mit der Materie vertraut gemacht habe.

    PS:Frohe Weihnacht.
    Lassen wir ersteinmal diesen Thread, ich will dich nicht am Heiligen Abend plagen, da ich heute ein Buch bekomme worin vielleicht ein Erklärung zu finden ist.

    cu max



  • Master_Max schrieb:

    Ich dachte das dies nur für char arrays gilt.

    Ich meine das \n (newline) Zeichen, dass uU noch am Ende vom string stehen kann - weil du ja eine ganze Zeile ausgelesen hast...

    Shade Of Mine schrieb:

    und vorallem: was machst du bei zB
    satisfy und als Antwort müsste dann ja gelten 'zufriedenstellen', 'befriedigen',...

    wie löst du dieses Problem?

    Sorry, ich verstehe deine Frage nicht.
    Du musst wissen das ich sehr neu in C++ bin und mich noch nicht wirklich mit der Materie vertraut gemacht habe.

    Ich meine damit eigentlich, dass Vokabeln nicht 1:1 übersetzt werden können, und man deshalb mehrere richtige Antworten geben kann.

    Da ich kein französich kann, bringe ich eben englisch<->deutsch beispiele.

    zB
    bedeutet satisfy ja sowohl 'befriedigen' als auch 'zufriedenstellen'
    oder run heisst sowohl 'laufen' als auch 'rennen'

    das ist kein Programmierproblem - sondern ich wollte dich lediglich darauf hinweisen...



  • Hi,

    Shade Of Mine schrieb:

    Ich meine das \n (newline) Zeichen, dass uU noch am Ende vom string stehen kann - weil du ja eine ganze Zeile ausgelesen hast...

    Ich dachte eigentlich das an einen string den ich mit cin einlese auch ein \n angehängt wird, falls das nicht der Fall sein sollte werde ich wohl mit
    getline(cin,)arbeiten müssen.
    Ich werde aber heute Abend wohl nicht mehr dazu kommen....

    Shade Of Mine schrieb:

    Ich meine damit eigentlich, dass Vokabeln nicht 1:1 übersetzt werden können, und man deshalb mehrere richtige Antworten geben kann.

    Da ich kein französich kann, bringe ich eben englisch<->deutsch beispiele

    Achso, sorry, ich war ein bisschen im Weihnachtsstress 🙄 .
    Naja ich habe die Vokabeln aus dem Französisch-Buch abgetippt und erwarte halt die Antworten die da drinnen stehen. Das ganze soll ja nicht
    komerziell oder so werden, sondern nur den Schülern meiner Schule beim Vokabellernen ein bisschen unter die Arme greifen, deshalb ist die einzige lösung die ich dazu anbieten kann eine dritte datei (Französisch) zu machen, wo ein gleichbedeutendes Wort an der Zeile steht und das ganze dann mit dem oder Operator lösen.

    Shade Of Mine schrieb:

    das ist kein Programmierproblem - sondern ich wollte dich lediglich darauf hinweisen...

    Danke ich hatte ehrlich gesagt noch gar nicht drangedacht. 🙄

    Ich wünsche dir und allen anderen dadrausen ein schönes Fest und eine zufriedenstellende Bescherung :xmas1: (falls sie noch nicht war).

    PS:Das gute an dem Programm soll sein das man später(ich werde ermitteln wo das ende der Datei ist)einfach andere Textdateien benutzen kann, das Programm wird das nicht weiter jucken.

    cu max



  • Hi,
    oder noch einfacher:

    string eingabe;
    cin >> eingabe;
    eingabe=+"\n";
    

    Vielen dank.

    cu max



  • Hi,
    ich habe beides ausprobiert, leider ohne erfolg.
    Irgendwo habe ich mal gehört das man das letzte einlesen löschen muss,
    mit cin.sync(); oder soetwas, ich werde mich mal informieren, vielleicht
    bringt das die Lösung.

    cu max



  • string InVoc;
    cin >> InVoc;
    cin.sync();
    cin.clear();
    

    Hat das Problem mit dem einlesen und somit dem falschen Vergleich tatsächlich beseitigt.:D
    Jetzt habe ich nur noch das Problem mit den Deutschen umlauten in der Konsole und ein paar französischen Fehlern. Ich hoffe das mit der FAQ lösen zu können.

    Vielen dank @Shade Of Mine.

    cu max


Anmelden zum Antworten