Frage zu Programmabbruch

LadyMarion

Mitglied
Hallo,

hab mal wieder eine Frage:

Ich habe eine Datei, in der jede Zeile folgendermaßen aufgebaut ist:
key | value | comment

Ich möchte nun über eine map mit dem key auf den value zugreifen, was ich in folgender Funktion bereits realisiert habe:
Code:
1  bool read() {
2      map<string, double> data;
3      ifstream IN ("test.txt");
4      if (IN.is_open()) {
5          string line;
6           while (getline(IN, line)) {
7              stringstream sstr;
8              string pipe, key, comment;
9              double value;
10             sstr << line;
11             sstr >> key >> pipe >> value >> pipe >> comment;
12             data[key] = value;
13         }
14         IN.close();
15         return true;
16     } else {
17         cout<<"ERROR opening test.txt\n";
18         return false;
19     }
20 }

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.

Also im Prinzip soll für die Zeile 12 sowas in der Art eingefügt werden:
Code:
if (/* also wenn der key tatsächlich existiert */) {
    data[key] = value;
} else {
    cerr <<"# Invalid key! Program terminated!"<<endl;
    exit(1);
}

Gibt es da eine Möglichkeit für so eine Anweisung oder brauch ich dafür extra eine Funktion, die ich aufrufe und die das überprüft?

Könnt Ihr mir da weiterhelfen?

Vielen Dank schon mal!
 
Hi.
Code:
if (/* also wenn der key tatsächlich existiert */) {
    data[key] = value;
} else {
    cerr <<"# Invalid key! Program terminated!"<<endl;
    exit(1);
}

Gibt es da eine Möglichkeit für so eine Anweisung oder brauch ich dafür extra eine Funktion, die ich aufrufe und die das überprüft?
Deine Frage ist also lediglich, ob es eine Anweisung gibt, mit der man feststellen kann, ob ein bestimmter Schlüssel in einer std::map existiert oder nicht?!

Ja, gibt es:
C++:
data.count(key) > 0
Alternativ kannst du auch die Methode std::map::find() verwenden, dann hast du gleich einen Iterator für den key und kannst den Wert ändern. Das würde eine Suche ersparen (erste Suche um zu schauen ob es drin ist, zweite Suche um den Wert zu ändern).

Gruß
 
Hi,

irgendwas mach ich falsch...

Wenn ich es mit "data.count(key) > 0" mache, dann wird das Programm entweder immer oder nie abgebrochen, je nachdem wo ich das count einbaue.
Mit "find" habe ich es davor auch schon versucht, aber das hat ebenfalls nicht funktioniert. :confused:
 
Also ich weiß einfach nicht, an welcher Stelle ich das einbauen sollte....

Wenn meine Datei, die eingelesen werden soll, folgendermaßen aussieht:
Code:
ABC | 1.2 | Kommentar
DEF | 3.4 | Kommentar

In der read-Funktion wird es so eingelesen, dass die map (data[key] = value) ja quasi so aussieht:
data["ABC"] = 1.2
data["DEF"] = 3.4

Jetzt 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.

Wenn ich das count nun aber so einbaue, dann findet er ja immer einen key, der eingelesen wurde:
Code:
1  bool read() {
2      map<string, double> data;
3      ifstream IN ("test.txt");
4      if (IN.is_open()) {
5          string line;
6           while (getline(IN, line)) {
7              stringstream sstr;
8              string pipe, key, comment;
9              double value;
10             sstr << line;
11             sstr >> key >> pipe >> value >> pipe >> comment;
12             data[key] = value;
13             if (data.count(key) == 0) {
14                 cerr<<"ERROR"<<endl;
15                 exit(1);
16             }
17         }
18         IN.close();
19         return true;
20     } else {
21         cout<<"ERROR opening test.txt\n";
22         return false;
23     }
24 }
 
Hi.

Irgendwie versteh ich deine Logik noch nicht. Du mußt doch erstmal die komplette Datei einlesen bevor du weißt welche Schlüssel es gibt und welche nicht. Oder sind die Schlüssel fest vorgegeben?

Während des Einlesens kannst du höchstens überprüfen ob ein Schlüssel bereits existiert, und dann Abbrechen (falls die Schlüssel nicht mehrfach auftreten dürfen).
LadyMarion hat gesagt.:
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
Nachdem die Datei eingelesen ist, müßtest du vor dieser Zuweisung Testen ob der Schlüssel in der map ist. Eine Funktion getValueOrDie()wäre sicherlich vorteilhaft...

Du könntest natürlich auch mit Exceptions arbeiten, die du später wieder abfangen kannst.

Gruß
 
Hallo,

jetzt hätte ich da nochmal eine Frage dazu:

Ich könnte das doch auch so machen, dass ich den Indexoperator der map so überlade, dass dort immer geprüft wird, ob der Schlüssel existiert oder nicht?

Der Operator an sich ist ja nicht das Problem, aber wie das mit dem Überladen genau funktioniert, das weiß ich nicht... Ich habe ja keine eigene map-Klasse, sondern verwende ja die STL-Klasse...
Könnt Ihr mir da vielleicht nen Tipp geben, wie sowas funktioniert?

Vielen Dank!!
 
Hi.
Ich könnte das doch auch so machen, dass ich den Indexoperator der map so überlade, dass dort immer geprüft wird, ob der Schlüssel existiert oder nicht?
...und dann eine Exception auslöst? Dann müßtest du ja zum Einfügen die insert Methode verwenden.

Ich halte das für keine gute Idee.
Der Operator an sich ist ja nicht das Problem, aber wie das mit dem Überladen genau funktioniert, das weiß ich nicht... Ich habe ja keine eigene map-Klasse, sondern verwende ja die STL-Klasse...
Könnt Ihr mir da vielleicht nen Tipp geben, wie sowas funktioniert?
Man könnte theoretisch eine von std::map abgeleitete Klasse erstellen und den Operator überladen. Aber damit handelt man sich mehr Probleme ein, als einem lieb sein kann...

Gruß
 
Zurück