fstream-Problem



  • Moin 😉
    Ich habe ein Problem. Und zwar möchte ich mit C++ eine Datei auslesen, dies bekomme ich auch mehr oder weniger hin, mit getline().
    Das Problem ist aber, dass ich nicht eine Zeile auslesen möchte, sondern einen Teil einer Zeile. Dafür wollte ich eigentlich read verwenden. Soweit mein Code:

    string str;
    ifstream f("test.txt", ios::in);
    
    f.seekg(6, ios::beg);
    f.read(str, sizeof(str));
    cout << str << endl;
    
    cin.get();
    return 0;
    

    Hier ist das ganze mit tDaten gemacht. Aber ich habe keine Ahnung was das ist und weiß auch nicht, wie ich danach in Google suchen sollte...
    Hier ist buffer ein Zeiger, oder? Wenn ja, dann verstehe ich die Zeile "buffer = new char [length];" nicht. Da würde Buffer ja theoretisch dann auf einen C-String zeigen. Ich kenne das aber nur mit "buffer=&newchar[length];"

    Ich weiß echt nicht weiter und bitte um Hilfe.



  • istream::read liest rohe Bytes und interpretiert diese nicht. Dh. das Lesen in ein Stringobjekt ergibt unter GHarantie nichts als Mist.

    Das Problem ist aber, dass ich nicht eine Zeile auslesen möchte, sondern einen Teil einer Zeile. Dafür wollte ich eigentlich read verwenden.

    Erklär mal was genau, dann kann man dir besser helfen.



  • Ethon schrieb:

    [...] Erklär mal was genau, dann kann man dir besser helfen.

    In test.txt steht beispielsweise der Inhalt

    Hallo ich bin ein Test
    

    in einer Zeile.
    In dem Programm möchte ich dann aber nur "ich bin ein Test" ausgeben.


  • Mod

    JFaron schrieb:

    Ethon schrieb:

    [...] Erklär mal was genau, dann kann man dir besser helfen.

    In test.txt steht beispielsweise der Inhalt

    Hallo ich bin ein Test
    

    in einer Zeile.
    In dem Programm möchte ich dann aber nur "ich bin ein Test" ausgeben.

    Und was macht in diesem Beispiel aus, dass das Hallo nicht mitgenommen werden soll? Dass es das erste Wort ist?



  • SeppJ schrieb:

    [...] Und was macht in diesem Beispiel aus, dass das Hallo nicht mitgenommen werden soll? Dass es das erste Wort ist?

    Das verstehe ich jetzt nicht. Das Hallo soll im Programm nicht ausgegeben werden, das hat keinen besonderen Grund, sondern ist nur eine Verdeutlichung von dem was ich möchte.



  • Er hat dich gefragt, nach welchem Kriterium du auswählst, welcher Teil der Zeile dich interessiert.



  • .. worauf SeppJ wahrscheinlich hinaus will ist. Könnte da auch ein
    "Hallilalo ich bin ein Text"
    stehen?
    Ist es immer das erste Wort, was Du nicht haben willst, oder sind es immer exakt 6 Zeichen?

    Kommt nach .. Text" noch irgendwas oder ist da immer die Zeile zu Ende?



  • Ach so, danke Ethon und Werner_logoff. In diesem speziellen Fall möchte ich immer die ersten sechs Zeichen nicht ausgeben. Der ausgegebene Text soll also die komplette Zeile ohne den ersten sechs Zeichen sein. (Rein aus Interesse: Wie würde man denn bestimmte Wörter, also z. B. das erste und das letze, wegfallen lassen?)



  • mache es so:

    #include <iostream>
    #include <fstream>
    #include <string>
    
    int main()
    {
        using namespace std;
        string str;
        ifstream f("test.txt");
        f.ignore(6); // überspringe die ersten 6 Zeichen
        if( getline( f, str ) ) // liest alles bis Zeilenende
            cout << "Gelesen: " << str << endl;
        return 0;
    }
    

    Einzelne Worte (oder Zahlen) liest Du mit dem operator>>. Der sollte auch immer die erste Wahl beim Lesen sein.

    Ändere dazu die Zeile 11 nach:

    if( f >> str ) // liest das folgende Wort
    

  • Mod

    JFaron schrieb:

    Ach so, danke Ethon und Werner_logoff. In diesem speziellen Fall möchte ich immer die ersten sechs Zeichen nicht ausgeben. Der ausgegebene Text soll also die komplette Zeile ohne den ersten sechs Zeichen sein. (Rein aus Interesse: Wie würde man denn bestimmte Wörter, also z. B. das erste und das letze, wegfallen lassen?)

    In beiden Fällen gleich: ignore, dann Rest der Zeile lesen (z.B. mit getline). Im Falle, dass man genau 6 Zeichen überspringen will, gibt man eben diese Zahl bei ignore an, im Falle, dass man das erste Wort überspringen will, gibt man bei ignore ein Leerzeichen als Trennzeichen an.

    edit: Zu spät. Ja, operator>> ist auch gut zum Wörter überspringen, dann gehen auch andere Whitespaces als Trennzeichen.



  • Ich danke euch beiden.
    Ich teste das nun, bei Problemen melde ich mich. Noch eine Frage zum Operator: Liest der nicht nur bis zum ersten Leerzeichen aus?

    edit: Und wofür ist der Header <string>? Und was genau bringt das if? Die Bedingung ist das Auslesen? Heißt, wenn nichts ausgelesen werden kann, wird auch nichts ausgegeben, richtig?
    edit3: Kann man mit ignore auch eine ganze Zeile überspringen? edit4: Habe einfach die Anzahl der Zeichen aus der Zeile darüber zu den 6 addiert. Funktioniert 😉



  • JFaron schrieb:

    Ich danke euch beiden.
    Ich teste das nun, bei Problemen melde ich mich. Noch eine Frage zum Operator: Liest der nicht nur bis zum ersten Leerzeichen aus?

    Ja - operator>> string liest ein Wort, und das endet mit dem ersten nicht druckbaren Zeichen oder EOF.

    JFaron schrieb:

    edit: Und wofür ist der Header <string>?

    für std::string, dort ist u.a. auch getline( std::istream&, std::string& ) definiert.

    JFaron schrieb:

    Und was genau bringt das if?

    Ein std::istream ist in einen boolschen Ausdruck konvertierbar. Der liefert 'faske', wenn ein Fehler aufgetreten ist.

    JFaron schrieb:

    Die Bedingung ist das Auslesen? Heißt, wenn nichts ausgelesen werden kann, wird auch nichts ausgegeben, richtig?

    .. wenn ein Fehler beim Lesen aufgetreten ist, wird nichts ausgegeben.

    JFaron schrieb:

    edit3: Kann man mit ignore auch eine ganze Zeile überspringen?

    Ja - mit ignore( std::numeric_limits< std::streamsize >::max(), '\n' );



  • Danke 👍

    Andere Frage, ähnliches Thema: Ich lese in das Programm einen Pfad per Tastatur ein. Dieser Pfad wird gespeichert in string path. Bevor ich nun weitermache, möchte ich die Existenz einer Datei in diesem Pfad testen, path/test.exe
    Wenn ich das per cout<< ausgebe, bekomme ich den Pfad so angezeigt, wie ich ihn haben will. Wenn ich aber

    if ("ifstream check(path/test.exe)")
            cout<<"weitermachen ";
        else cout << "fehler";
    

    schreibe, wird immer weitermachen ausgegeben, auch wenn ich statt test.exe test.txt schreibe, welche dort gar nicht existiert. Was mache ich falsch bzw. wie sollte ich die Existenz einer Datei anders abfragen?


  • Mod

    JFaron schrieb:

    Was mache ich falsch bzw. wie sollte ich die Existenz einer Datei anders abfragen?

    Derzeit hast du magisches Denken. Glaubst du, dass bei

    if ("Moderiert Thomas Gottschalk noch Wetten dass?")
     cout << "Ja.";
    else
     cout << "Nein.";
    

    wirklich geprüft wird, was Thomas Gottschalk derzeit macht? Nein, es wird bloß die Adresse eines Zeichenkettenliterals ausgewertet und geprüft, ob diese 0 ist oder nicht.

    Du kannst eine Datei auf Existenz prüfen, indem du sie zum Lesen öffnest, funktioniert dies, so existiert sie. Dazu musst du aber wirklich ein Streamobjekt anlegen, nicht bloß den Code dazu in ein Zeichenkettenliteral schreiben. Wenn du feiner aufgelöste Details wissen möchtest (z.B. vielleicht existiert die Datei, aber du darfst sie nicht lesen) musst du auf Betriebssystemfunktionen zurückgreifen.



  • Stimmt, war ein Denkfehler drin :p
    Habs jetzt mit

    ifstream check("path/test.exe");
    if (check) {
        ...
    } else {
    ...
    }
    

    gelöst. Aber nun wird immer die Ausgabe bei else verwendet...


  • Mod

    JFaron schrieb:

    Aber nun wird immer die Ausgabe bei else verwendet...

    Dann wurde die Datei wohl nicht geöffnet.



  • SeppJ schrieb:

    JFaron schrieb:

    Aber nun wird immer die Ausgabe bei else verwendet...

    Dann wurde die Datei wohl nicht geöffnet.

    Das komische ist ja, dass ich den Pfad mehrfach überprüfe, jedes mal. Auch wenn er richtig ist, komme ich bei else raus... Der Code an sich stimmt aber?!
    Ich habe es sowohl mit einfachem und doppeltem Backslash und dem normalen Slash getestet. (Der normale müsste funktionieren, der doppelte auch, der einfache nicht, oder?)



  • Vorgehen:
    1. Gib den Pfad absolut an - so hast Du keine Probleme mit dem Working Directory
    2. Versuche ob / oder \ (bzw. \) benötigt wird

    Dann müsstest Du eigentlich zum Ziel kommen...



  • theta schrieb:

    Vorgehen:
    1. Gib den Pfad absolut an - so hast Du keine Probleme mit dem Working Directory
    2. Versuche ob / oder \ (bzw. \) benötigt wird

    Dann müsstest Du eigentlich zum Ziel kommen...

    Ich habe die entsprechenden Zeilen jetzt einfach kopiert. Im ersten Fall "path/test.exe" lande ich bei der "else-Ausgabe". Im Zweiten Fall "C:/Program Files (x86)/test/test.exe" ist die Bedingung wahr. Die Eingabe in path habe ich jetzt per Datei gemacht, so dass ich Schreibfehler auch ausschließen kann.



  • Das hier:

    "path/test.exe"
    

    und das hier:

    "C:/Program Files (x86)/test/test.exe"
    

    ist ja auch ein himmelweiter Unterschied!


Anmelden zum Antworten