find und replace von CR/LF



  • Hallo

    ich versuche gerade mein erstes kleines Programm in C++ zu erstellen und komme an einer Stelle nicht weiter.

    Ich will in einer vorhandenen TXT-Datei alle CR/LF durch TAB ersetzen und daher habe ich folgendes geschrieben:

    // Beha_Con.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
    //
    
    #include "stdafx.h"
    #include <fstream> 
    #include <iostream> 
    #include <string> 
    using namespace std; 
    
    int main() 
    { 
         ifstream iStream("Beha.esca");       
         ofstream tempStream("Beha.txt"); 
         string s; 
         while (getline(iStream, s))  { 
    		 while(s.find("[\n]", 0) < s.length())     
    	s.replace(s.find("[\n]", 0), 1, "\t");
             tempStream << s << endl; 
         } 
    
         iStream.close(); 
         tempStream.close(); 
    }
    

    Leider kann ich die Zeilenwechsel mit dem Programm nicht finden obwohl ich sie im HEX-Editor sehen kann.

    Vielleicht habt Ihr ja einen Tip für einen echten Anfänger

    Gruß
    Axel



  • std::string str = "Blub\na\nb\nc";
    
    std::cout << "Vorher: " << str << "\n";
    
    std::size_t pos;
    while ((pos = str.find("\n")) != std::string::npos)
    {
    	str[pos] = '\t';
    }
    
    std::cout << "Nachher: " << str << "\n";
    


  • Oder noch als elegantere Variante:

    #include <algorithm>
    // ...
    std::replace(str.begin(), str.end(), '\n', '\t');
    


  • sehe ich das richtig das mein Fehler am Namespace lag?

    Ich will ja auch was lernen!

    Danke
    Axel



  • Nein, mit dem std:: (Namespace) hat das nichts zu tun. Dein Fehler liegt schon mal daran, dass du [\n] geschrieben hast, aber eigentlich nach \n suchen wolltest.

    Wenn find nichts finden, dann wird string::npos zurückgegeben. Du kannst also auf s.find(...) != string::npos prüfen.

    Ansonsten ist s.replace und replace etwas anderes.

    Dein Code würde evtl. so funktionieren

    while(s.find("\n", 0) != string::npos)    
     s.replace(s.find("\n", 0), 1, "\t");
    

    Wenn man das replace aber vereinfacht, dann macht es nix anderes als

    s[s.find("\n", 0)] = '\t';
    


  • getline verwirft die Zeilenenden. Wie willst du dann welche im gelesenen String finden?



  • Es gibt eine schöne Lösung mit Stream-Iteratoren:

    #include <iostream>
    #include <algorithm>
    #include <iterator>
    #include <fstream>
    
    int main()
    {
         std::ifstream iStream("Beha.esca");
         std::ofstream tempStream("Beha.txt");
    
         std::replace_copy( std::istream_iterator<char>(iStream >> std::noskipws), std::istream_iterator<char>(), std::ostream_iterator<char>(tempStream), '\n', '\t' );
    }
    

    (Ungetestet)

    Edit: noskipws eingefügt - jetzt sollte es gehen.



  • istream_iterator<char> verwirft Whitespaces.



  • Sone schrieb:

    Es gibt eine schöne Lösung mit Stream-Iteratoren:

    #include <iostream>
    #include <algorithm>
    #include <iterator>
    #include <fstream>
    
    int main()
    {
         std::ifstream iStream("Beha.esca");
         std::ofstream tempStream("Beha.txt");
    
         std::replace_copy( std::istream_iterator<char>(iStream), std::istream_iterator<char>(), std::ostream_iterator<char>(tempStream), '\n', '\t' );
    }
    

    (Ungetestet)

    most vexing parse



  • Nathan schrieb:

    istream_iterator<char> verwirft Whitespaces.

    Editiert!

    Aber most vexing parse hat doch hiermit nix zu tun... 😕

    Edit: Ahh, out hat schon geantwortet. 👍



  • out schrieb:

    most vexing parse

    Quatsch, was red ich denn, hier gibts ja kein "Problem" damit.



  • Sone schrieb:

    Es gibt eine schöne Lösung mit Stream-Iteratoren:

    #include <iostream>
    #include <algorithm>
    #include <iterator>
    #include <fstream>
    
    int main()
    {
         std::ifstream iStream("Beha.esca");
         std::ofstream tempStream("Beha.txt");
    
         std::replace_copy( std::istream_iterator<char>(iStream), std::istream_iterator<char>(), std::ostream_iterator<char>(tempStream), '\n', '\t' );
    }
    

    (Ungetestet)

    Gehts noch langsamer? Da muss ein istreambuf_iterator her.



  • die schrieb:

    Sone schrieb:

    Es gibt eine schöne Lösung mit Stream-Iteratoren:

    #include <iostream>
    #include <algorithm>
    #include <iterator>
    #include <fstream>
    
    int main()
    {
         std::ifstream iStream("Beha.esca");
         std::ofstream tempStream("Beha.txt");
    
         std::replace_copy( std::istream_iterator<char>(iStream), std::istream_iterator<char>(), std::ostream_iterator<char>(tempStream), '\n', '\t' );
    }
    

    (Ungetestet)

    Gehts noch langsamer? Da muss ein istreambuf_iterator her.

    Das war auch nur die grundlegende Idee.
    Natürlich geht auch mit Streambuffer-Iteratoren:

    std::replace_copy( std::istreambuf_iterator<char>(iStream), std::istreambuf_iterator<char>(), std::ostreambuf_iterator<char>(tempStream), '\n', '\t' );
    


  • Sone schrieb:

    std::istreambuf_iterator<char>(iStream >> std::noskipws)
    

    Nein, du hast istreambuf_iteratoren noch nicht verstanden.



  • die schrieb:

    Sone schrieb:

    std::istreambuf_iterator<char>(iStream >> std::noskipws)
    

    Nein, du hast istreambuf_iteratoren noch nicht verstanden.

    Wieso? Funktionieren tut es doch. Mit C++11 natürlich. Habs getestet, der Output ist richtig. Meinst du dass ich sie nicht richtig verwende?



  • Sone schrieb:

    Meinst du dass ich sie nicht richtig verwende?

    Jo.
    istream_iterator ist formatiert: Vor jedem char ein sentry erstellen, laaahm.
    istreambuf_iterator gibt dir die Rohdaten.

    std::noskipws ist nur für den istream_iterator notwendig, das für einen istreambuf zu verwenden zeugt von Unkenntnis.



  • Edit: Hast Recht.



  • Ufz, danke für die vielen Infos die muß ich erst mal verdauen.

    Oder ich starte wieder bei "Hello World" 😢

    Axel



  • axel99 schrieb:

    Ufz, danke für die vielen Infos die muß ich erst mal verdauen.

    Nö, musste nicht.

    Aber es kann nicht schaden, dir mal Stream-Iteratoren anzugucken (und mir auch nicht 😃 ), die sind - wie du sehen kannst - ganz nützlich, weil man dadurch Dateien (bzw. Streams oder Streambufs) mit Iteratoren darstellen und dann an STL-Algos übergeben kann.


Anmelden zum Antworten