Datei auslesen funktioniert nicht
-
Hallo, ich möchte eine Textdatei mit folgendem Inhalt auslesen:
eins||||zwei|drei|||| vier||fuenf|||||| ||||sechs|| siebenDas Programm soll die senkrechten Striche ignorieren und die Strings einzeln
ausgeben. Ein Versuch wäre:#include <iostream> #include <string> #include <fstream> using namespace std; int main() { ifstream filestream("test.txt",ios::out); string s,a; while(filestream.good()) { getline(filestream,s); for (int i=0;i<s.size();++i) { if (s[i]=='|') //Wenn Zeichen='|' neuer Schleifendurchlauf { continue; } else if (s[i]!='|' && s[i-1]=='|') //Wenn das Zeichen ungleich "|" und das vorherige Zeichen = "|" ist, //wird der String ausgegeben und gelöscht. { cout<<a<<endl; a.clear(); } a+=s[i]; //Zeichen wird zum String addiert. } } return 0; }Die Ausgabe ist leider fehlerhaft und ich weiß nicht, wo der Fehler steckt:
eins zwei dreivier fuenf
-
getline kennt einen Parameter delim.
-
Ok, also mit delim könnte das so aussehen:
while(filestream.good()) { getline(filestream,s,'|'); cout<<s; }Sieht schonmal nicht schlecht aus, allerdings werden die Strings nacheinander
ausgegeben, also einfach ohne die Trennzeichen.
Eine formatierte Ausgabe mit z.B. einem Leerzeichen zwischen den Strings
funktioniert nicht, z.B.:while(filestream.good()) { getline(filestream,s,'|'); cout<<s<<" "; }
-
Edit: falsch
-
Also, das funktioniert bei mir:
#include <iostream> #include <sstream> int main() { std::istringstream ss("eins||||zwei|drei||||"//Für dein "Szenario" einfach statt istringstream ss... ifstream ss("Dateiname"); "vier||fuenf||||||" "||||sechs||" "sieben "); for(std::string s;getline(ss, s, '|');std::cout << s << ((s.empty())? " \b" : " ")); }
-
Ja, das funktioniert bis auf eine Kleinigkeit bei der Ausgabe.
(Am Zeilenanfang bei "sechs" wird auch ein Leerzeichen gesetzt.)
Schon erstaunlich, wie schwierig das ist, ein paar Zeichen aus einem String
zu filtern.
-
Folgendes Programm funktioniert bei mir:
#include <algorithm> #include <iterator> #include <string> #include <iostream> #include <sstream> #include <fstream> int main() { std::ifstream f("test.txt", std::ios::in); std::string s; std::copy(std::istream_iterator<char>(f), std::istream_iterator<char>(), std::back_inserter(s) ); s = std::string(s.begin(), std::unique(s.begin(), s.end() ) ); std::replace(s.begin(), s.end(), '|', '\n'); std::cout << s; if(*s.rbegin() != '\n') std::cout << "\n"; }
-
pyhax schrieb:
Folgendes Programm funktioniert bei mir:
#include <algorithm> #include <iterator> #include <string> #include <iostream> #include <sstream> #include <fstream> int main() { std::ifstream f("test.txt", std::ios::in); std::string s; std::copy(std::istream_iterator<char>(f), std::istream_iterator<char>(), std::back_inserter(s) ); s = std::string(s.begin(), std::unique(s.begin(), s.end() ) ); std::replace(s.begin(), s.end(), '|', '\n'); std::cout << s; if(*s.rbegin() != '\n') std::cout << "\n"; }Keinen Bock das zu analysieren (auch wenn es eine Minuten dauert)
Ist es besser als meins? (böse-guck)Edit: Schon passiert.
-
Ja, sieht gut aus.
Die Ausgabe ist fehlerfrei.
Die STL ist schon verdammt mächtig.thx@all
-
Es hat nur einen kleinen Bug: |||aa||bb|| wird zu:
a bDas könnte man mit einem eigenen Vergleichsoperator beheben: (mit C++11 Lambdas ginge das ohne extra Funktion)
#include <algorithm> #include <iterator> #include <string> #include <iostream> #include <sstream> #include <fstream> template <char Ch> bool compareAndEqual(char c1, char c2) { return (c1 == c2) && c1 == Ch; } int main() { std::ifstream f("test.txt", std::ios::in); std::string s; std::copy(std::istream_iterator<char>(f), std::istream_iterator<char>(), std::back_inserter(s) ); if(s.size() == 0) return 0; s = std::string(s.begin(), std::unique(s.begin(), s.end(), compareAndEqual<'|'>) ); std::replace(s.begin(), s.end(), '|', '\n'); if(*s.begin() == '\n') s.erase(s.begin() ); std::cout << s; if(*s.rbegin() != '\n') std::cout << "\n"; }Außerdem wird geprüft, ob die Ausgabe mit einem Zeilenumbruch beginnt, und wenn wird dieser abgeschnitten.
-
int main() { const char* filename = "test.txt"; ifstream file(filename); istream_iterator<char> iter1(file), iter2; std::string file_contents(iter1, iter2); file.close(); cout << regex_replace(file_contents, regex("\\|+"), string("\n")) << endl; return 0; }
-
pyhax und Hacker sind einfach putzig. Langsamere und unschönere Lösungen (die auch noch verbuggt sind) fallen mir kaum ein.
#include <iostream> #include <fstream> class my_facet : public std::ctype<char> { mask my_table[table_size]; public: my_facet() : std::ctype<char>(my_table) { std::copy(classic_table(), classic_table() + table_size, my_table); my_table['|'] |= (mask) (space); } }; int main() { std::ifstream fs("test.txt"); fs.imbue(std::locale(std::locale(), new my_facet())); for (std::string s; fs >> s;) std::cout << s << '\n'; }Statt der for-loop kann man natürlich auch das folgende verwenden:
std::copy(std::istream_iterator<std::string>(fs), std::istream_iterator<std::string>(), std::ostream_iterator<std::string>(std::cout, "\n"));