Komplette Zeile mit Whitespaces einlesen, ohne getline



  • Abend,
    es gab hier mal die Aussage, dass man getline eigentlich nicht bräuchte, wenn man die Features von istream richtig nützte. Wenn ich nun von der Console eine Zeile mit Whitespaces einlesen möchte, wie mache ich dass dann ohne getline?

    std::string str( (std::istream_iterator<char>(cin>>std::noskipws)), std::istream_iterator<char>() );
    

    So geht es ja leider nicht, da kann ich lange tippen. 😃

    Hat jemand eine Idee, abgesehen von

    std::string str;
    for(char c; cin.get(c), c!='\n'; str+=c);
    

    Danke im Voraus.

    edit: Aufgrund SeppJs Beitrag.



  • Was spricht denn gegen getline ?



  • Oberon_0 schrieb:

    Was spricht denn gegen getline ?

    Hier die entsprechenden Stellen von Werner 🙂

    1. http://www.c-plusplus.net/forum/p2193436?highlight=getline#2193436
    2. http://www.c-plusplus.net/forum/p1653228#1653228


  • Mod

    Gugelmoser schrieb:

    Oberon_0 schrieb:

    Was spricht denn gegen getline ?

    Hier die entsprechenden Stellen von Werner 🙂

    1. http://www.c-plusplus.net/forum/p2193436?highlight=getline#2193436
    2. http://www.c-plusplus.net/forum/p1653228#1653228

    Du hast nicht verstanden, was Werner damit sagen wollte. Versuch es noch einmal zu verstehen, der Hinweis ist, wie alles was Werner über Streams schreibt, gut.



  • Gugelmoser schrieb:

    Oberon_0 schrieb:

    Was spricht denn gegen getline ?

    Hier die entsprechenden Stellen von Werner 🙂

    1. http://www.c-plusplus.net/forum/p2193436?highlight=getline#2193436
    2. http://www.c-plusplus.net/forum/p1653228#1653228

    Hallo Gugelmoser,

    meine - durchaus provokant gemeinte - Aussage 'getline ist doof' bezieht sich auf die Tatsache, dass getline sehr häufig dazu genutzt wird, Zeichen aus einer Datei in den Speicher zu schaufeln, um sie anschließend zu parsen. Die Leute sind so auf das getline fixiert, dass es sogar dazu benutzt wird, eine Datei in eine andere zu kopieren.
    Der Missbrauch liegt in der Tatsache, dass das spätere Parsen entweder mit string-Operationen geschieht, wozu std::string nicht gemacht wurde oder dadurch dass man die Zeichenkette wiederum in einen stringstream schreibt, um es erneut zu interpretieren. Im zweiten Fall macht man eine (unnötige) Kopie, verliert die locale und hätte ja auch gleich aus dem Original-Stream lesen können - mal abgesehen von dem endl-Problem. Aber lassen wir das hier mal beiseite.

    getline liest Zeichen 'unformatiert' - im Gegensatz zu allen istream-Streaming-Operatoren, die alle formatiert lesen. Oder flapsig ausgedrückt, die istream-Streaming-Operatoren lesen schlau - und getline eben doof.

    Wenn Du tatsächlich alle Zeichen bis zum nächsten Zeilenende einlesen möchtest, weil Du diese Zeichenkette genau so als Input Deines Programms benötigst, dann - und genau dann- ist getline die erste Wahl. Aber nach meinen Erfahrungen ist das eher die Ausnahme.
    Also kommt automatisch die Nachfrage - wofür brauchst Du das?

    Gruß
    Werner



  • Werner Salomon schrieb:

    Wenn Du tatsächlich alle Zeichen bis zum nächsten Zeilenende einlesen möchtest, weil Du diese Zeichenkette genau so als Input Deines Programms benötigst, dann - und genau dann- ist getline die erste Wahl. Aber nach meinen Erfahrungen ist das eher die Ausnahme.
    Also kommt automatisch die Nachfrage - wofür brauchst Du das?

    Hallo Werner,
    ich habe eine kleine Consolen-Application geschrieben, die zum einen Dateinamen von Musikfiles auf ein bestimmtes Format prüft und zum anderen prüft, ob der Dateiname mit mit den ID3v1-Tags Interpret und Titel übereinstimmt.

    So, nun zu getline :

    1. Die Applikation erwartet als Eingabe (in der Konsole) den Pfad zu den Musikfiles, und ein Pfad kann ja Leerzeichen enthalten. Dann habe ich mich irgendwie daran erinnert, dass du mal geschrieben hattest, dass getline doof sei. Dann hatte ich mich gefragt, wie ich nun eine Zeichenkette mit Whitespaces am besten einlesen sollte.

    2. Die Applikation schreibt ihre Ergebnisse in die ausgabe.txt Datei. Die Ausgaben habe ich natürlich etwas übersichtlicher gestaltet (sprich Zeilenumbrüche). Nun will ich aus dieser File alle Zeilen auslesen, in denen vorkommt "no mp3 but wma". Und hier hätte ich nun auch wiederum getline genommen... Und hier ein Ausschnitt aus ausgabe.txt :

    Format error, no mp3 but wma.
    >Beach Boys - I Get Around.wma
    

    Wäre in diesen Fällen nun getline für mich angebracht?



  • Gugelmoser schrieb:

    Die Applikation erwartet als Eingabe (in der Konsole) den Pfad zu den Musikfiles, und ein Pfad kann ja Leerzeichen enthalten.

    dann nimm getline - Du brauchst einen String, Du liest einen String - what else

    Gruß
    Werner



  • Gugelmoser schrieb:

    1. Die Applikation erwartet als Eingabe (in der Konsole) den Pfad zu den Musikfiles, und ein Pfad kann ja Leerzeichen enthalten. Dann habe ich mich irgendwie daran erinnert, dass du mal geschrieben hattest, dass getline doof sei. Dann hatte ich mich gefragt, wie ich nun eine Zeichenkette mit Whitespaces am besten einlesen sollte.

    Du willst getline() verwenden um Commandline-Parameter einzulesen?
    Oder stehen die Dateinamen in einem File, das du Zeile für Zeile einlesen willst?



  • hustbaer schrieb:

    Gugelmoser schrieb:

    1. Die Applikation erwartet als Eingabe (in der Konsole) den Pfad zu den Musikfiles, und ein Pfad kann ja Leerzeichen enthalten. Dann habe ich mich irgendwie daran erinnert, dass du mal geschrieben hattest, dass getline doof sei. Dann hatte ich mich gefragt, wie ich nun eine Zeichenkette mit Whitespaces am besten einlesen sollte.

    Du willst getline() verwenden um Commandline-Parameter einzulesen?
    Oder stehen die Dateinamen in einem File, das du Zeile für Zeile einlesen willst?

    Nein, ich verwende getline um den Pfad des Verzeichnisses einzulesen, in dem sich die zu prüfenden Audiofiles befinden, also z.B. D:\Musik . Den ganzen Rest übernimmt dann boost::filesystem3, also das Iterieren über alle im Verzeichnis enthaltenen Files.



  • Wieso verwendest du dann nicht einfach argc/argv?



  • hustbaer schrieb:

    Wieso verwendest du dann nicht einfach argc/argv?

    Da müsste ich die exe stets über die Kommandozeile aufrufen. Ich habs aber lieber, wenn ich einfach nur ein Doppelklick machen muss. Oder ruft ihr eure Applicationen immer via Kommandozeile auf?


  • Mod

    Gugelmoser schrieb:

    hustbaer schrieb:

    Wieso verwendest du dann nicht einfach argc/argv?

    Da müsste ich die exe stets über die Kommandozeile aufrufen. Ich habs aber lieber, wenn ich einfach nur ein Doppelklick machen muss. Oder ruft ihr eure Applicationen immer via Kommandozeile auf?

    Klar. Wer einmal die Kommandozeile gewöhnt ist, für den ist Klickibunti bloß noch plump und umständlich. Denk doch nur, was du derzeit machen musst: Erst Hand an die Maus, Geste ausführen, Doppelklicken. Dann Hand an die Tastatur. Pfad komplett eintippen, Enter drücken.

    Kommandozeile: Hand an Tastatur, erste paar Zeichen von Anwendung, Tab, erste paar Zeichen von Pfad, Tab, Enter. Viel schneller Workflow mit viel weniger Bewegung und ohne Wechsel.

    Man braucht natürlich eine vernünftige Shell dafür.



  • SeppJ schrieb:

    Man braucht natürlich eine vernünftige Shell dafür.

    Die da z.B. wären? :p



  • bash ... 🤡


  • Mod

    Ethon schrieb:

    bash ... 🤡

    Genau. Wobei die anderen typischen Verdächtigen wie csh oder zsh auch ganz gut sind. Empfehlenswert ist aber (auch allgemein zum Programmieren) eine US-Englische Tastatur, sonst stirbt man an den Sonderzeichen.



  • Gugelmoser schrieb:

    hustbaer schrieb:

    Wieso verwendest du dann nicht einfach argc/argv?

    Da müsste ich die exe stets über die Kommandozeile aufrufen. Ich habs aber lieber, wenn ich einfach nur ein Doppelklick machen muss. Oder ruft ihr eure Applicationen immer via Kommandozeile auf?

    Nö.
    Es gibt da was ganz tolles das nennt sich Batchfile 🙂
    Oder auch GetPrivateProfileStringW.
    (OK, das ist Windows-only, aber in der Boost gibt's sicher auch was um Config-Files zu lesen)



  • Gugelmoser schrieb:

    hustbaer schrieb:

    Wieso verwendest du dann nicht einfach argc/argv?

    Da müsste ich die exe stets über die Kommandozeile aufrufen. Ich habs aber lieber, wenn ich einfach nur ein Doppelklick machen muss.

    Nach dem Doppelklick musst du ja doch noch tippen. Nicht viel gewonnen also.
    Stattdessen könntest du per Rechtsklick auf das Ziel (in deinem Fall das Verzeichnis) ein öffnen mit... oder senden an... aufrufen und dann dein Programm auswählen. Vorausgesetzt, dein Programm akzeptiert den Pad als Kommandozeilenparameter...



  • @pumuckl
    Ich hatte angenommen dass er den Pfad aus einem Config-File ausliest.



  • hustbaer schrieb:

    Ich hatte angenommen dass er den Pfad aus einem Config-File ausliest.

    Wozu braucht er dann noch argc/argv?



  • Gar nicht.
    Das war bloss meine Frage wieso er eben nicht argc/argv verwendet.


Anmelden zum Antworten