C++: Zeichen aus Datei einlesen
-
Hallo,
Ich habe folgenden Code. Aber ich bekommen die Fehlermeldung " Segmentation fault (core dumped)" Hat jemand ne Idee?
#include <iostream> #include <vector> #include "ReadFile.h" using namespace std; bool l = false, w = false, c = false; int lcount = 0, wcount = 0, ccount = 0, abcount = 0; int main(int argc, char *argv[]){ vector<string> parms; //hier werden später die Kommandozeilenargumente (KA) gespeichert while(--argc){parms.push_back(argv[argc]);} //Übergabe der KA an parms, von hinten nach vorne string filename = parms[0]; //parms[0] ist der Dateiname der TXT, da von hinten gezählt wurde //Überprüfung ob die Parameter korrekt eingegeben worden -l, -w, -c for(int i=0;i<parms.size();++i){ if(i==0){filename = parms[i];} // der letzte Parameter ist der Dateiname (in diesem Fall: loreipsum-utf8.txt) else if(parms[i]=="-l"){l = 1;} // es wurde ein Parameter "-l" uebergeben -> l = true else if(parms[i]=="-w"){w = 1;} // "" "-w" "" -> w = true else if(parms[i]=="-c"){c = 1;} // "" "-c" "" -> c = true } // Abbruchbedingung falls KA nicht korrekt sind. if( !l || !w || !c){ cout << "Usage: gip-wc -w -l -c filename" << endl; return 0;} //Einlesen der Datei ReadFile F(filename); bool absatz(false); //Brauchen wir um später die Absätze von den gezählten Wörtern ab zu ziehen, da sonst jeder Absatz als Wort gezählt wird while(!F.eof()){ //Schleife zu Zählen der Zeilen (lcount), Wörter (wcount) und Zeichen (ccount) char zeichen = F.GetChar(); //Aktuelles Zeichen abfragen if(F.eof()) break; //Abbruch am Ende der Datei if(zeichen){ccount++;} //Bei jedem Zeichen wird gezählt if(isspace(zeichen)){wcount++;} //Bei jedem Leerzeichen, oder neuen Zeile wird ein Wort gezählt if(zeichen != '\n'){absatz=0;} //Wenn keine neue Zeile vorliegt kommt auch kein Absatz mehr if(absatz){ //Falls aus der Vorschleife eine neue Zeile vorkam... if(zeichen == '\n'){abcount++; absatz=1;} //wird jetzt geprüft ob wieder eine neue Zeile folgt und dementsprechend ein Absatz gezählt } if(zeichen == '\n'){lcount++; absatz=1;} //Zeilen werden gezählt und ein möglicher Absatz wird eingeleitet } int ges_wcount = wcount-abcount; //Final wird vom Zähler der die Wörter gezählt hat, noch die Absätze abgezogen, damit die Zahl auch stimmt //Ausgabe cout << endl; cout << "Die Datei \"" << filename << "\" hat: " << endl; cout << "\t" << lcount << " Zeilen"<< endl; cout << "\t" << ges_wcount << " Woerter" << endl; cout << "\t" << ccount << " Zeichen"<< endl; return 0; }
Mit folgender Header Datei:
#include<fstream> #include<string> class ReadFile { private: std::string filename; std::fstream file; public: ReadFile(std::string f) { filename = f; try { file.open(filename.c_str(), std::fstream::in | std::ios::binary); } catch( ... ) { std::cout << "Datei existiert nicht!\n"; }; } ~ReadFile() { file.close();} bool eof(){ return file.eof(); } char GetChar() { char c = file.get(); if (!file.eof()) return c; } }; //using namespace std; #endif /* __READFILE_H__*/
-
Fehler in GetChar?
siehe auch https://www.c-plusplus.net/forum/p2437138#2437138
-
Hallo jokki58,
Willkommen im C++-Forum.
jokki58 schrieb:
Ich habe folgenden Code. Aber ich bekommen die Fehlermeldung " Segmentation fault (core dumped)" Hat jemand ne Idee?
Zwei Stellen kommen in Betracht.
1.) Im Konstruktor von ReadFile wirfst Du eine Exception, die nirgendwo gefangen wird. Das sollte zwar keinen 'Segmentation fault' auslösen, aber ein ungewolltes Programmende. Dass die Exception geworfen wird, ist sehr wahrscheinlich, weil 'parms[0]' in Zeile 15 nicht der Dateiname, sondern der letzte Parameter ist.
2.)
jokki58 schrieb:
char GetChar() { char c = file.get(); if (!file.eof()) return c; }
.. was soll das Programm machen, wenn file.eof()
false
liefert? Und irgendwann passiert das immer.Gruß
Werner
-
Werner Salomon schrieb:
1.) Im Konstruktor von ReadFile wirfst Du eine Exception, die nirgendwo gefangen wird. Das sollte zwar keinen 'Segmentation fault' auslösen, aber ein ungewolltes Programmende. Das die Exception geworfen wird, ist sehr wahrscheinlich, weil 'parms[0]' in Zeile 15 nicht der Dateiname, sondern der letzte Parameter ist.
Ich würde jetzt sagen, dort wird eine Exception gefangen, die niemals geworfen wird. Deshalb wird auch nicht festgestellt, dass die Datei nicht geöffnet werden kann.
-
@manni66: Stimmt!
-
Vielen Danke. Aber ich sitz jetzt auf der Leitung. Wie kann ich den Fehler beheben sprich was muss ich am Code ändern?
-
z.B.
class ReadFile { private: std::string filename; std::fstream file; public: ReadFile(std::string f) { filename = f; file.open(filename.c_str(), std::fstream::in | std::ios::binary); } bool eof(){ return file.eof(); } bool good() { return file.good(); } char GetChar() { return file.get(); } };
und
ReadFile F(filename); if(!F.good() ) { std::cerr << "Fehler\n"; exit(1); }
-
und wo ist der witz darin einen ifstream so zu kapseln, wenn man ihn genausogut "pur" verwenden könnte?
-
mit dem neuen Code bekomme ich einen Fehler dass filename nicht deklariert ist.. der ist aber deklariert
-
-
Swordfish schrieb:
und wo ist der witz darin einen ifstream so zu kapseln, wenn man ihn genausogut "pur" verwenden könnte?
Nirgendwo. Der Prof/Hiwi ist zu blöd, etwas ordentliches zu schreiben.
-
jokki58 schrieb:
Vielen Danke. Aber ich sitz jetzt auf der Leitung. Wie kann ich den Fehler beheben sprich was muss ich am Code ändern?
dann hast Du u.U.das #include <string> vergessen oder gelöscht.
Ich habe mir mal erlaubt, das Ganze zu überarbeiten:
#include <iostream> #include <vector> #include <fstream> // .. keine globalen Variablen int main(int argc, char *argv[]){ using namespace std; if( argc < 2 ) { cout << "Usage: gip-wc -w -l -c filename" << endl; return 0;} // wozu die Optionen ?? const char* filename = argv[argc-1]; // reicht auch, statt std::string ifstream F( filename ); if( !F.is_open() ) { cout << "Fehler beim Oeffnen der Datei '" << filename << "'" << endl; return 0; } int lcount = 0, wcount = 0, ccount = 0, abcount = 0; // lokal deklarieren enum Letztes_zeichen_typ { ANFANG, SPACE, NEUE_ZEILE, ABSATZ, SONSTIGES } letztes_zeichen = ANFANG; F >> noskipws; // Leerzeichen mit lesen for( char zeichen; F >> zeichen; ++ccount ) { if( zeichen == '\n' ) { ++lcount; // Zeilen zählen if( letztes_zeichen == SONSTIGES ) ++wcount; // Wort endete mit '\n' if( letztes_zeichen == NEUE_ZEILE ) { ++abcount; letztes_zeichen = ABSATZ; // so wird dreimal neue Zeile nicht als zwei Absätze gezählt. } else if( letztes_zeichen == SONSTIGES || letztes_zeichen == SPACE ) letztes_zeichen = NEUE_ZEILE; } else if( isspace( zeichen ) ) { if( letztes_zeichen == SONSTIGES ) ++wcount; letztes_zeichen = SPACE; } else { // sonstiges letztes_zeichen = SONSTIGES; } } // -- Nachbehandlung if( letztes_zeichen == SONSTIGES || letztes_zeichen == SPACE ) { ++lcount; ++abcount; } else if( letztes_zeichen == NEUE_ZEILE ) { ++abcount; } //Ausgabe cout << endl; cout << "Die Datei \"" << filename << "\" hat: " << endl; cout << "\t" << lcount << " Zeilen"<< endl; cout << "\t" << wcount << " Woerter" << endl; cout << "\t" << ccount << " Zeichen"<< endl; cout << "\t" << abcount << " Absaetze" << endl; return 0; }
Gruß
Werner
-
Danke Werner. Jetzt klappt es teilweise Ich kompilier das Programm aber dann muss ich ja " gip-wc -w -l -c filename" eingeben aber dann sagt der mir " gip-wc : command not found" woran liegt das?
-
Dein Programm liegt nicht in den Verzeichnissen der PATH Environmentvariablen.
Auf Linux kannst du mal ./gip-wc probieren, wenn das Programm im aktuellen Verzeichnis ist.
Welches System/Compiler/IDE nutzt du?
-
Das Programm funktioniert jetzt. Vielen Dank an alle