Bei std::getline() Zeilenumbruch immer entfernen?

T_55

Lieutenant
Registriert
Feb. 2013
Beiträge
638
Hallo,

gestern hab ich mehrere Stunden mit Fehlersuchen verbracht um dann festzustellen, dass std::getline() den String immer mit dem Zeilenumbruch \r\n liefert. Per std::cout schwer zu finden da unsichtbar. Der Fehler ist bei der Prüfung zweier Strings auf Gleichheit aufgetereten.
Mit der Zeile zeile.erase(zeile.find_last_not_of("\r\n")+1); funktioniert jetzt alles:
C++:
std::string zeile;
while(std::getline(file,zeile))
{
   zeile.erase(zeile.find_last_not_of("\r\n")+1);
   // usw
}
Vorher habe ich eher Zahlen ausgelesen per std:stof etc dort ist mir nie ein Fehler aufgetreten, kann std:stof und Konsorten mit Zeilenumbrüchen umgehen? Ich überlege, ob ich jetzt generell bei std::getline() lieber immer die oben gezeigte Zeile anwende.
Frage 1: kann man std::getline() dazu bringen den Zeilenumbruch erst gar nicht in den String zu stecken?
Wenn nein:
Frage 2: Sollte man generell bei der Verarbeitung von Zeilen von std::getline() die \r\n löschen? Oder ist das nur beim Usecase Stringvergleich notwendig?
Frage 3: Es gibt \n oder \r oder \r\n. Bei mir funktioniert die obige Löschaktion nur wenn dort "\r\n" oder "\r" eingetragen ist. Um alles abzudecken zB Datenquellen von Unix Mac und Windows müsste man dann eigentlich alle Varianten abfragen richtig?. Wird ja auch alles nicht performanter mit den ganzen Zusatzprüfungen.

Grüße
 
std::getline() tut
  • unter Windows ('\r\n') im "textmodus", also std::ifstream fh("name.ext")
    • '\r', '\n' entfernen
    • '\n' entfernen
  • unter Windows im "binärmodus", also std::ifstream fh("name.ext", std::ios::binary)
    • bei '\r', '\n' nur '\n' aber nicht '\r' entfernen
    • '\n' entfernen
  • unter Unix ('\n') im "textmodus", also std::ifstream fh("name.ext")
    • bei '\r', '\n' nur '\n' aber nicht '\r' entfernen
    • '\n' entfernen
  • unter Unix im "binärmodus", also std::ifstream fh("name.ext", std::ios::binary)
    • bei '\r', '\n' nur '\n' aber nicht '\r' entfernen
    • '\n' entfernen
Wenn Du mit unterschiedlichen Files arbeitest und nicht vorher weißt, welche Endzeichen vorkommen können, mußt Du Dir was einfallen lassen. Eine Quick-and-dirty-Variante wäre die Abwandlung Deines schon geposteten Codes:
C++:
void chomp(std::string& line, const char* trail)
{
size_t pos = line.find_first_of(trail);
if (pos != std::string::npos)
    line.erase(pos);
}

int main(int argc, char*argv[])
{
... 
std::ifstream fh("name.ext", std::ios::binary);
std::string line;
while (std::getline(fh, line)) {
    chomp(line, "\n\r");
    ...
    ...
}
...
}
 
  • Gefällt mir
Reaktionen: T_55
Super Danke, damit kann man schon mal beim Auslesen die Sache bereinigen.

Ich hab noch ein paar Tests gemacht und festgestellt, dass Dateien die unter Unix erstellt werden in Unix und Windows bei getline kein Endzeichen haben. Aber, dass Dateien die bei Windows erstellt werden nur in Windows bei getline kein Endzeichen haben. Das heißt nur wenn Daten von Windows zu Unix kommen gibt es das Problem.

Jetzt wäre doch als Alternative zur Bereinigung, dass man einfach alle Endzeichen im Unix-Style speichert.
Da Komische ist, ich definiere zum Schreiben der Datei beim ofstream im Windows-Programm myfile << "\n"; und trotzdem wird es wohl im Windows-Style "\r\n" gespeichert und so von getline unter Unix nicht entfernt. Der gleiche Code mit der Speicherung "\n" führt also unter Windows und Unix zu unterschiedlichen Endzeichen!
Damit zur Preisfrage, wie kann ich bei einem Windows-Programm das Unix-Endzeichen(\n) in eine Datei einfügen als wäre es unter Unix erstellt worden? Denn myfile << "\n" funktioniert leider nicht.

Grüße
 
T_55 schrieb:
wie kann ich bei einem Windows-Programm das Unix-Endzeichen(\n) in eine Datei einfügen als wäre es unter Unix erstellt worden? Denn myfile << "\n" funktioniert leider nicht.
Indem Du unter Windows die Datei im Binärmodus geöffnet hast: std::ofstream fh("name.ext", std::ios::binary)
 
  • Gefällt mir
Reaktionen: T_55
Zurück
Oben