ifstream exception
-
Hallo!
Ich sag's gleich: ist mein erster Eintrag hier, also seid bitte nicht zu grob!
Ich habe ein Problem mit einer intern ausgelößten Exception. Code:
void CHumanNameDatabase::load_names(const string& filename) { ifstream file; string line; unsigned int line_num = 1; // enable the exceptions for this ifstream-instance file.exceptions(ifstream::failbit | ifstream::badbit); try { // try to open the file file.open(filename.c_str()); if (file.is_open()) { while(getline(file,line,'\n')) { // as lond as the end of the file is not reached if (line[0] != '#' && !line.empty()) { // line is no comment and isn't empty try { CHumanName* name = CParser::get_instance().parse_human_name(line); add_name(name->get_name(),name->get_sex()); delete name; } catch (CSyntaxCommandException& exc) { cout << "Line " << line_num << ": " << exc.what() << endl; /* FIXXXME: will later be replaced by a call to CError::Error */ } } line_num++; } file.close(); } } catch (ifstream::failure& exc) { CWarning::get_instance().warning("error while opening the human-names-file"); if (file.is_open()) file.close(); } /* FIXXXME: somehow, the try-catch code throws and exception every time, regardless if the file is existent or not ??? */ }
Es scheint mir, als würde getline() eine Exception werfen, wenn es am Ende des files angekommen ist, dabei will ich aber nur eine werfen, falls das file garnicht vorhanden ist.
Danke im Voraus,
Maximilian
-
Es scheint mir, als würde getline() eine Exception werfen, wenn es am Ende des files angekommen ist
Das hast dem Stream ja auch explizit befohlen. Du hast ihm gesagt, er soll eine Exception werfen, wann immer das failbit oder das badbit gesetzt werden. Da das Lesen von eof das failbit setzt, wird halt auch eine Exception geworfen.
dabei will ich aber nur eine werfen, falls das file garnicht vorhanden ist.
Noch machen Computer nur das was man ihnen sagt, nicht das was man hofft gesagt zu haben.
Du hast zwei Möglichkeiten:
1. Du wirfst selbst eine Exceptionifstream file; string line; unsigned int line_num = 1; try { // try to open the file file.open(filename.c_str()); if (!file.is_open()) throw std::runtime_error("could not open file"); ...
2. Du löschst die Exception-Maske nach dem Aufruf von is_open:
if (file.is_open()) { file.exceptions(ios::goodbit); ...
Btw: Die Verwendung von Exceptions ist hier völlig unnötig. Exceptions sind für Fälle in denen Code der ein Problem feststellt und Code der das Problem behandelt an unterschiedlichen Stellen liegt (meist auf unterschiedlichen logischen Ebenen). Hier behandelst du den Fehler aber direkt in der Funktion. Da reicht ein einfaches if.
Ich würde den Code in einem ersten Schritt erstmal wie folgt vereinfachen:void CHumanNameDatabase::load_names(const string& filename) { ifstream file(filename.c_str()); if (!file.is_open()) { CWarning::get_instance().warning("error while opening the human-names-file"); return; } unsigned int line_num = 1; for (string line; getline(file, line); ++line_num) { // Bedingung ist in deinem Code falschrum! if (!line.empty() && line[0] != '#') { try { // RAII macht die Freigabe von name Exception-sicher // Warum ist CHumanName kein Value-Type der by value geliefert wird? std::auto_ptr<CHumanName> name(CParser::get_instance().parse_human_name(line)); add_name(name->get_name(),name->get_sex()); } catch (const CSyntaxCommandException& exc) { // throw by value - catch by reference-to-const! cout << "Line " << line_num << ": " << exc.what() << endl; } } } }
-
Diese try/catch-Konstruktion habe ich von hier:
http://www.cplusplus.com/ref/iostream/ios/exceptions.html
Dabei hat mich das "opening" im Kommentar des catch-Teiles wohl auf die falsche Fährte geführt.[/quote]Btw: Die Verwendung von Exceptions ist hier völlig unnötig.[/quote]
Dann werde ich mich hier auf die Verwendung von if's beschränken.Da du sicher viel mehr Erfahrung mit C++ hast (ich lerne gerade), sind mir noch ein paar Dinge nicht ganz klar. Du verwendest z.B.: einen sogenannten "smart-pointer", wenn ich das richtig sehe. Das Wissen um diese habe ich mir noch nicht angeeignet, und außerdem "komme" ich von C, also bin ich noch ziemlich eingeschoßen auf die Verwendung von "normalen" Pointern.
Jedenfalls, danke!
-
Du verwendest z.B.: einen sogenannten "smart-pointer", wenn ich das richtig sehe. Das Wissen um diese habe ich mir noch nicht angeeignet
Vielleicht hilft das:
http://fara.cs.uni-potsdam.de/~kaufmann/?page=GenCppFaqs&faq=Leak#Answ
und das:
http://fara.cs.uni-potsdam.de/~kaufmann/?page=GenCppFaqs&faq=auto_ptr#Answ