std::string replace_all()?



  • Hallo,
    ich empfange in meinem Programm HTML-Quelltext und möchte diesen dann in einer Textbox darstellen. Wie ihr wisst, muss man dabei unter Windows einen Zeilenumbruch durch CRLF (\r\n) darstellen, die Server senden hingegen meist nur LF (\n).

    Hat jemand zufällig eine möglichst kompakte Funktion, um alle LF eines std::string durch CRLF zu ersetzen? Ich möchte ungern auf zusätzliche Bibliotheken zurückgreifen und es stattdessen mit Bordmitteln lösen. Oder ist das umständlich und man kann irgendwie einfach dem Server sagen, das er gleich die (für Windows) korrekte Version sendet?

    Das Problem ist ja auch, dass ein Suchen nach LF und einfaches Ersetzen nicht ausreicht, da man dann auch Ergebnisse im Falle eines bereits vorhandenen CRLF bekommt und man dann beim Ersetzen schließlich CRCRLF erhalten würde. Und reguläre Ausdrücke gehören ja leider auch nicht zum "Lieferumfang" von C++.

    Gruß
    ph4nt0m


  • Administrator

    Bist du dir sicher, dass die Textbox entsprechend reagiert? Früher war es mal so, aber ich dachte bei den neuere Windowsversionen sei dies nicht mehr der Fall.

    Ansonsten kannst du einfach über std::string::find nach '\r' suchen, prüfst ob es ein nächstes Zeichen hat, wenn dem der Fall ist schaust du ob es ein '\n' ist, wenn nicht dann fügst du über std::string::insert eines ein. Danach geht es weiter mit std::string::find, allerdings gibst du nun an, ab wo gesucht werden soll.

    Grüssli



  • ph4nt0m schrieb:

    Hat jemand zufällig eine möglichst kompakte Funktion, um alle LF eines std::string durch CRLF zu ersetzen?

    Der C++ Standard hat nichts zu bieten, man muss sich immer alles zusammenfrickeln.



  • Dravere schrieb:

    Bist du dir sicher, dass die Textbox entsprechend reagiert? Früher war es mal so, aber ich dachte bei den neuere Windowsversionen sei dies nicht mehr der Fall.

    Ja, zumindest die normalen Steuerelemente der Win32-API können mit einem einfachen \n nichts anfangen und drucken dann einen "Kasten".

    Dravere schrieb:

    Ansonsten kannst du einfach über std::string::find nach '\r' suchen, prüfst ob es ein nächstes Zeichen hat, wenn dem der Fall ist schaust du ob es ein '\n' ist, wenn nicht dann fügst du über std::string::insert eines ein.

    Naja, ein einzelnes \r wird wohl niemals vorkommen, sondern entweder nur ein \n oder eben \r\n. Das Problem ist, dass, wenn ich nach \n suche, ich nicht dieses einfach durch \r\n ersetzen kann, da in Wirklichkeit vor dem gefundenen \n bereits ein \r vorhanden sein könnte. Es scheint nämlich Server zu geben, die bereits "Windows-konform" senden.

    Wie auch immer, mit so einigen gesonderten Abfragen habe ich jetzt meiner Meinung nach beide Fälle abgedeckt:

    size_t pos = 0;
    while((pos = str.find(TEXT('\n'), pos)) != std::string::npos)
    {
    	if(pos == 0 || str.at(pos-1) != TEXT('\r'))
    		str.replace(pos, 1, TEXT("\r\n"));
    	pos += 2;
    }
    

    Wenn ihr spontan irgendwelche Fehler entdeckt, wäre es sehr nett, mir dies mitzuteilen 🙂


  • Administrator

    ph4nt0m schrieb:

    Naja, ein einzelnes \r wird wohl niemals vorkommen, ...

    Gibt es alte Mac Server? *hatte da aus irgendeinem Grund den alten Mac im Hinterkopf*

    ph4nt0m schrieb:

    Das Problem ist, dass, wenn ich nach \n suche, ich nicht dieses einfach durch \r\n ersetzen kann, da in Wirklichkeit vor dem gefundenen \n bereits ein \r vorhanden sein könnte.

    Gleiches Vorgehen wie mit meinem Algo, einfach einen Schritt rückwärts gehen 😉

    size_t pos = 0;
    while((pos = str.find(TEXT('\n'), pos)) != std::string::npos)
    {
    	if(pos == 0 || str.at(pos-1) != TEXT('\r'))
    		str.replace(pos, 1, TEXT("\r\n"));
    	pos += 2;
    }
    

    ph4nt0m schrieb:

    Wenn ihr spontan irgendwelche Fehler entdeckt, wäre es sehr nett, mir dies mitzuteilen 🙂

    Ja, da gibt es ein paar Fehler.
    1. Ich nehme mal an, dass str ein Objekt des Typs std::string ist, dann ist das Makro TEXT hier ganz sicher ein Fehler. std::string ist immer ein std::basic_string<char> . Mit dem Makro TEXT machst du aber aus den Literalen womöglich ein L'' oder L"" also ein wchar_t Literal.
    2. Wieso die at Funktion? Du kannst hier durch Logik garantieren, dass der Index immer im Bereich der Zeichenkette sein wird, da ist der zusätzliche Aufwand für die Prüfung unnötig. Nimmer lieber den operator[] .
    3. Wieso die replace Funktion? Du überschreibst ein Zeichen, welches bereits vorhanden ist. Nimm doch std::string::insert(pos, 1, '\r') .

    Grüssli



  • Danke für deine Antwort.

    Zu Punkt 1: Nein, es handelt sich um ein std::basic_string<TCHAR> Objekt und damit sollte das TEXT-Makro doch völlig korrekt sein. Oder gibt es einen anderen/besseren Weg, sein Programm nur durch Änderung einer einzelnen Anweisung/Option wahlweise mit oder ohne Unicode kompilieren zu können?

    Die anderen Punkte nehme ich aber dankend an 😋


  • Administrator

    ph4nt0m schrieb:

    Zu Punkt 1: Nein, es handelt sich um ein std::basic_string<TCHAR> Objekt und damit sollte das TEXT-Makro doch völlig korrekt sein.

    Oh! Ja.

    ph4nt0m schrieb:

    Oder gibt es einen anderen/besseren Weg, sein Programm nur durch Änderung einer einzelnen Anweisung/Option wahlweise mit oder ohne Unicode kompilieren zu können?

    Wie wäre es, wenn du ausschliesslich in Unicode kompilieren würdest? Das wäre zumindest einfacher 😉

    Grüssli


Anmelden zum Antworten