Programmabbruch funktioniert nicht
-
Hallo,
hab mal wieder eine Frage:
Ich habe eine Datei, in der jede Zeile folgendermaßen aufgebaut ist:
key | value | commentIch möchte nun über eine map mit dem key auf den value zugreifen, was ich in folgender Funktion bereits realisiert habe:
bool read() { map<string, double> data; ifstream IN ("test.txt"); if (IN.is_open()) { string line; while (getline(IN, line)) { stringstream sstr; string pipe, key, comment; double value; sstr << line; sstr >> key >> pipe >> value >> pipe >> comment; data[key] = value; } IN.close(); return true; } else { cout<<"ERROR opening test.txt\n"; return false; } }Soweit funktioniert alles, aber es könnte ja sein, dass man sich bei dem key vertippt oder einen key eingibt, der gar nicht vorhanden ist. Dies soll abgefangen werden, d.h. es soll eine Fehlermeldung ausgegeben und das Programm abgebrochen werden.
Jetzt habe ich für die Zeile 12 folgendes eingefügt.
if (line.find(key) != string::npos) { data[key] = value; } else { cerr <<"# Invalid key! Program terminated!"<<endl; exit(1); }So funktioniert es aber nicht. Wenn ich nun einen key eingebe, der nicht existiert, dann wird für den Wert 0 ausgegeben, aber das Programm läuft trotzdem normal weiter.
Was mach ich denn falsch? Könnt Ihr mir da weiterhelfen?
Vielen Dank schon mal!
-
Deine Abfrage "line.find(key)" ist ja ziemlich sinnlos, da du ja gerade vorher den "key" aus der Zeile "line" extrahierst hat.
-
Hmm da ist was nicht logisch ...
bool read() { std::ifstream file_stream("test.txt"); if (!file_stream) return false; std::map< std::string, double > data; std::string bin; std::string key; std::string value; while (file_stream >> key >> bin >> value >> bin >> std::getline(file_stream, bin)) data.insert(std::make_pair(key, value)); }... soweit ließt er ein, okay ... aber data ist nach verlassen von read doch eh nicht mehr da?!
-
Ja, stimmt, das ist wirkich sinnlos so. Jetzt ist es mir auch aufgefallen.
Also mit data kann ich eigentlich schon arbeiten. Wie gesagt, es funktioniert alles bis auf diesen Programmabbruch.
Kann ich das nicht direkt abfragen? Brauch ich da eine extra Funktion, die das überprüft?
-
Mach aus
if (line.find(key) != string::npos) {
einfach
if (data.find(key) == data.end()) {Das willst du doch testen, oder?
-
Irgendwas mach ich wohl falsch... So funktioniert es auch nicht... Das Programm läuft ganz normal weiter, auch wenn der Key nicht vorhanden ist.
-
Mit der Bedingung von Fellhuhn fügst Du den key in data ein, wenn er noch nicht existiert, und gibst eine Fehlermeldung aus, wenn er bereits existiert. Was möchtest Du denn sonst erreichen?
EDIT:
Beim Einlesen von Keys aus einer Datei kann ein Key falschgeschrieben sein?!
-
Also folgendes:
Meine Datei, die eingelesen wird, sieht folgendermaßen aus:
ABC | 1.2 | Kommentar DEF | 3.4 | KommentarIn der read-Funktion wird es so eingelesen, dass die map (data[key] = value) ja quasi so aussieht:
data["ABC"] = 1.2
data["DEF"] = 3.4Jetzt wird die read-Funktion in meinem Programm aufgerufen und dann die Werte zugewiesen, z.B.
double test = data["ABC"];
Und genau bei diesem Aufruf könnte ja sein, dass dort ein key steht, der gar nicht existiert, z.B. data["GHI"]. Und genau in dem Fall soll das Programm dann abbrechen.
-
if (data.find("KEY") == data.end()) { // Key existiert nicht ... /* Programmabbruch einleiten */ }Aber gewiss nicht in der read-Funktion, oder?
-
if (data.find("ABC") == data.end()) {
exit(1);
}
-
Ich habe die Problematik auch einmal aufgefasst und die Aussagen oben so gut es geht in einem lauffähigen Programm zusammen gefasst.
Folgende Anforderungen habe ich an das Programm gestellt:
* Die Abfrage des Schlüssel erfolgt nicht während des Einlesens
* Die Abfragefunktion beendet nicht das Programm, wenn kein Schlüssel gefunden wurde.In meinem Beispiel bricht das Programm nicht ab, sondern gibt eine Mitteilung aus, dass der Schlüssel nicht gefunden wurde.
#include <iostream> #include <fstream> #include <map> #include <sstream> #include <string> typedef std::pair<size_t, double> Result; typedef std::map<std::string, double> Database; void insertFromFile(const std::string& filename, Database&); Result selectFromDB(const std::string& key, const Database&); int main() { Database db; // ** Einlesen der Datenbank ** try { insertFromFile("test.txt", db); } catch(std::string e) { std::cerr << "Fehler!\n " << e << std::endl; return EXIT_FAILURE; } // ** Arbeiten mit der Datenbank ** Result r1 = selectFromDB("pi", db); if(r1.first > 0) { // Erwartetes Ergebnis: std::cout << "Pi ist " << r1.second << std::endl; } Result r2 = selectFromDB("a03", db); if(r2.first == 0) { // Erwartetes Ergebnis: std::cout << "a03 konnte nicht gefunden werden" << std::endl; } return EXIT_SUCCESS; } // ---------------------------------------------------------------------------- void insertFromFile(const std::string& filename, Database& d) { std::ifstream in(filename.c_str()); if(!in.is_open()) throw std::string("Datei konnte nicht geoeffnet werden!"); // std::string sollte eigentlich NICHT geworfen werden! std::string line; while(getline(in, line)) { std::stringstream ss(line); std::string key; char pipe; float value; ss >> key >> pipe >> value; // Der Rest der Zeile wird ohnehin verworfen d[key] = value; } } // ---------------------------------------------------------------------------- Result selectFromDB(const std::string& key, const Database& d) { size_t count = d.count(key); double value = 0.0; if(count > 0) value = d.find(key)->second; return std::make_pair(count, value); }Die Datenbasis:
a01 | 0.1234 | Kommentar beliebier Länge a02 | 1.3345 | - pi | 3.14157 | -Ich hoffe, dass Beispiel ist einigermaßen verständlich, auch wenn es nicht sonderlich gut kommentiert ist.
Grüße... Heiko