Zeilenumbruch aus String durch ein Zeichen ersetzen
-
Die erinnerung schrieb:
Was wäre das Ergebnis?
Datensalat: "-9" und zwei Sonderzeichen.
Deine Frage hat mich auf die Idee gebracht, den Code einfach mal so auszuprobieren. Also einfach einen
String erzeugt und mit einem Wert versehen und dann die Schleife hinterher, funktioniert einwandfrei, der Code
ist also richtig gewesen.
Die gepostete Schleife war nur Teil eines Programms, welches im Vorfeld eine Datei ausliest und den Inhalt
in ein CharArray umwandelt, welches anschließend in einen String übertragen wird. Mir ist bewußt, daß man das auch anders programmieren kann, was ich eben auch mal getan habe, auch das funktioniert einwandfrei.
Ich hatte den Codeteil nur aus Bequemlichkeit übernommen, müßte so aber auch funktionieren normalerweise.#include <iostream> #include <string> #include <fstream> using namespace std; int main() { int length; ifstream filestream("test.txt",ios::binary); filestream.seekg(0,ios::end); length=filestream.tellg(); filestream.seekg(0,ios::beg); char buffer[length]; filestream.read(buffer,length); //filestream.close(); string s=buffer; for(unsigned int i=0;i<s.size();++i) { if (s[i]=='\n') //oder if (s[i]=='\r\n') { s[i]='-'; } } cout<<s; return 0; }
-
gelöscht
-
Wurstinator schrieb:
http://www.cplusplus.com/reference/algorithm/replace/
int main () { string foo = "345\n67\n8\n9"; replace(foo.begin(), foo.end(), '\n', ' '); cout << foo << endl; return 0; }
Incocnito schrieb:
Also so klappts:
#include <iostream> #include <string> int main() { std::string s = "5\n4\n123\n"; for(auto iter = s.begin(); iter != s.end(); ++iter) if(*iter == '\n') *iter = 'x'; std::cout << s; //5x4x123x }
Thx, so geht es mit Iteratoren.
-
Soll dein Code irgendwie das hier machen?
#include <iostream> #include <fstream> #include <string> int main() { std::ifstream datei("datei.dat"); char c; std::string s; while(datei.get(c)) if(c == '\n') s.push_back('-'); else s.push_back(c); std::cout << s; }
-
buffer ist nicht nullterminiert; dementsprechend erzeugt
string s=buffer;
undefiniertes Verhalten, und danach ist alles reine Glückssache.
Versuch's mal mit
string s(buffer, buffer + length);
Ansonsten geht das auch einfacher mit Stringstreams:
#include <algorithm> #include <fstream> #include <iostream> #include <sstream> int main() { std::ifstream file("test.txt"); std::ostringstream buffer; buffer << file.rdbuf(); std::string s = buffer.str(); std::replace(s.begin(), s.end(), '\n', '-'); std::cout << s; }
-
seldon schrieb:
Ansonsten geht das auch einfacher mit Stringstreams:
#include <algorithm> #include <fstream> #include <iostream> #include <sstream> int main() { std::ifstream file("test.txt"); std::ostringstream buffer; buffer << file.rdbuf(); std::string s = buffer.str(); std::replace(s.begin(), s.end(), '\n', '-'); std::cout << s; }
Ja, thx.
seldon schrieb:
buffer ist nicht nullterminiert; dementsprechend erzeugt
string s=buffer;
undefiniertes Verhalten, und danach ist alles reine Glückssache.
Ok, dann müßte man doch einfach das Array um ein Element größer erzeugen und an die letzte Stelle
die Nullterminierung einfügen können.char buffer[length+1]; ... buffer[length+1]='\0';
seldon schrieb:
Versuch's mal mit
string s(buffer, buffer + length);
Sry, das funktioniert leider nicht.
-
Was steht denn in der Datei drin, und was kriegst du mit nullterminiertem Buffer als Ausgabe?
Das einzige, was mir so spontan noch auffällt, ist das ios::binary beim Öffnen der Datei. Wenn du unter Windows arbeitest, könntest du auf die Art Strings der Form "Zeile1\r-Zeile2\r-Zeile3\r-" bekommen, und da \r ein Steuerzeichen (gehe zum Anfang der Zeile) ist, dürfte das auf der Konsole komisch aussehen (in diesem Fall "-eile3" mit dem Cursor auf dem ersten 'e').
-
Also mit Nullterminiertem Array sieht der Code dann so aus:
#include <iostream> #include <string> #include <fstream> #include <string.h> using namespace std; int main() { int length; ifstream filestream("test.txt",ios::binary); filestream.seekg(0,ios::end); length=filestream.tellg(); filestream.seekg(0,ios::beg); char buffer[length+1]; filestream.read(buffer,length); buffer[length+1]='\0'; string s=buffer; for(unsigned int i=0;i<s.size();++i) { if (s[i]=='\r\n') // ohne '\r' ist die Ausgabe nur Datensalat. { s[i]='-'; } } cout<<s; }
Ausgabe erfolgt mit einem Sonderzeichen am Ende, das wird dann wohl das '\0' sein.
Allerdings werden die Zeilenumbrüche nicht entfernt.
Interessant ist, daß wenn man man die If-Abfrage nur mit "\r" schreibt, das dann am Ende jeder
Zeile das "\r" durch "-" ersetzt wird. Die Zeilenumbrüche bleiben aber trotzdem bestehen.
Schätze aber auch, daß das mit ios::binary zu tun hat. Irgendwie werden da die Steuerzeichen "vermurkst".
-
ohne den rest angeguckt zu haben:
char buffer[length+1]; //kein standard c++ - nimm std::vector filestream.read(buffer,length); buffer[length+1]='\0'; // !!! buffer[length] - dann hättest du im debug-mode hier auch nen assert gehabt...
bb
-
Statt
ifstream filestream("test.txt",ios::binary);
schreib mal
ifstream filestream("test.txt");
Unter Windows werden Textdateien so behandelt, dass Zeilenenden durch "\r\n" dargestellt werden (also zwei Zeichen). Wenn du die Datei im Textmodus öffnest, übernimmt das System die Umwandlung für dich, mit ios::binary kriegst du den Kram halt in Rohfassung und müsstest das \r selbst ignorieren. \r bedeutet "geh wieder zum Anfang der Zeile zurück", und das führt natürlich zu seltsamer Ausgabe, wenn man es einfach drinlässt.
-
Ja, das funktioniert. Danke für die direkte Info.
Du hast absolut Recht, in binärer Form werden alle Zeichen, also auch diverse
Steuerzeichen mit übertragen, allerdings nicht nur '\r\n', denn sonst könnte man die einfach mitremove (s.begin(), s.end(), '\n'); replace (s.begin(), s.end(), '\r','-');
entfernen. Was aber nicht funktioniert, es werden immer noch 2 Sonderzeichen mit
ausgegeben
Ich habe mir deshalb mal den Spass gemacht, die Zeichen des Strings mitint zahl; for(unsigned i=0;i<s.size();++i) { zahl=s[i]; cout<<zahl<<endl; }
einzeln als ASCII-Zeichen ausgeben zu lassen. Das Ergebnis sind 15 Zeichen(!),
7 sind Zahlen, 6 sind '\r\n', bleiben also 2 übrig. Eines davon könnte
die Nullterminierung sein, aber das andere?
Sind übrigens ASII: 21 und 64.
-
Meintest du
s.erase(remove(s.begin(), s.end(), '\n'), s.end());
?
-
Ja, das geht natürlich auch.
Allerdings verbleiben auch da 2 Zeichen im String.