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.