Konzept gesucht: Sprachdatei verwalten für Fehlermeldungen im Programm



  • Hallole.

    Ich hoffe ich kann meine Frage hier verständlich ausführen...

    In meinem Programm habe ich verschiedene Fehler- und Statusmeldungen.
    Die Fehlermeldungen habe ich mit einer fortlaufenden Fehlernummer versehen, damit ich im Falle eines Fehlers beim Kunden genau nachsehen kann wo der Fehler auftritt.

    Das Prinzip ist foldendes:

    Ich schreibe in eine Textdatei immer in 10er Gruppen die Texte:

    #100-109#
    Fehlernummer (100)
    Fehlernummer (101)
    Fehlernummer (102)
    Fehlernummer (103)
    Fehlernummer (104)
    Fehlernummer (105)
    Fehlernummer (106)
    Fehlernummer (107)
    Fehlernummer (108)
    Fehlernummer (109)

    #110-119#

    Fehlenummer (110)
    User Ausgeloggt (111)
    Datensocket erstellt (112)
    Keine Verbindung zur Software (113)
    .....

    So sieht das aus.
    Für diese Textdatei habe ich ein Programm geschrieben welches die TExte einliest und in eine *.lng DAtei schreibt. So kann man die Texte übersetzen.

    Während der Laufzeit lese ich die entsprechenden TExte aus.
    Dafür habe ich eine Funktion, der ich die ensprechende Textnummer übergebe.
    //FKT_fehlertext(110);

    Somit erreiche ich, daß jede Fehlernummer nur einmal vorkommt und ich im Pogramm genau feststellen kann wo der Fehler auftritt.

    Mein Problem ist sicherlich aus dem Beispiel ersichtlich:
    ICh habe ca 1000 Fehlermöglichkeiten.
    Dazu miss ich aber 1000x "Fehlernummer (...)" in die Textdatei schreiben, was ja Platzverschwendung ist.

    Viel Lieber wäre es mir, wenn ich die wiederholbaren Texte einmalig reinschreibe und die Fehlernummer hintendran hänge.

    Nur ist die Funktion so aufgebaut, daß das übergeben Argument eben der auszulesende Index ist.

    Übergebe ich nun immer 100 für "Fehlernummer" liest er immer "Fehlernummer (100)" aus.
    KLar kann ich das in Klammer stehende weglassen,aber wie bekomme ich dann meine EINDEUTIGE Fehlernummer?
    Nach dem bisheringe System war es nicht mögloch, daß irgendeine Fehlernummer zweimal vorkommt, da ich ja sehe welche position schon besetzt ist.

    Ich habe schon mit einem 2. Argument rumexperimentiert, zb. 1 Arg: Index, 2. Arg. Fehlernummer.
    Aber dann müsste ich mir irgendwi die letzte, die höchste Fehlernummer notieren, was in meinem letzten Programm schon schiefgegangen ist.
    Außerdem werde ich dann irgendwann mit dem Index in Konflikt kommen.

    Wie also kann ich das machen, daß ich wiederholbare Texte nur einmal reinschreibe und trotzdem eine eindeutige Fehlernummer habe?



  • Ich würde die möglichen Meldungen in einer map<int,string> speichern und suchen - Einträge mit dem Dafault-Wert brauchst du dann nicht zu speichern (genauer ist es umgekehrt: wo kein Wert vorliegt, wird der Default genommen):

    map<int,string> fehler;
    string default_fehler;
    
    string fehlermeldung(int num)
    {
      map<int,string>::iterator pos = fehler.find(num);
      if(pos!=fehler.end())
        return pos->second;
      else
        return default_fehler + " ("+lexical_cast<string>(num)+")";
    }
    


  • Hmmm..gute Idee.
    Aber woher weiß ich dann, welche Fehlernummer ich schonmal verwendet habe und welche nicht?
    Genau das ist ja mein Problem.
    Wenn ich 1000x Fehlernummer (...) in die DAtei schreibe, dann sehe ich genau welche position schon besetzt ist und welche nicht.
    Ich mache dann einfach in der nächsten weiter.

    Übergebe ich wahllos Fehlernummmer, verliere ich irgendwann den Überblick und es kann sein, daß die eine oder andere 2 und 3mal vorkommt....

    Oder hab ich was falsch verstanden?



  • Mondmann schrieb:

    Aber woher weiß ich dann, welche Fehlernummer ich schonmal verwendet habe und welche nicht?

    Indem du in diese map<> guckst (die kannst du am Programm-Anfang aus der Datei auslesen) - der Ausdruck fehler.find(num) gibt entweder einen Iterator zu einem map-Eintrag zurück (wenn die Nummer bereits vergeben ist) oder fehler.end() (wenn die Nummer noch "frei" ist).



  • Ja schon, aber:
    Ich vergebe die Fehlernummern ja fest im Programm, während dem Programmieren.
    Füge ich einen neuen Programmblock hinzu, können daraus zb. 10 neue Fehler entstehen.
    Ich führe dann die Fehlernummer einfach weiter: FKT_fehlertext(110)..
    FKT_fehlertext(111) usw...

    Woher weiß ich denn jetzt ob ich diese Zahlen nicht schon in einem anderen Programmblock verwendet habe?



  • Naja, irgendwo und wann muß halt auch der Mensch mal nachdenken. 😃 Du kannst doch in die Textdatei schauen, was die letzte Fehlernummer ist. Mit der machst du weiter. Letzte Nummer 101? Du brauchst eine neue Fehlermeldung? Also kommt 102 dran. Trägste in die Textdatei "102 blablabla" ein und in deinen Source FKT_fehlertext(102).



  • Nein nein.. 🙂
    Es geht ja eben darum ,daß ich nicht jedesmal "Fehlernummer XXX" in die Textdatei schreiben, sonden eben nur "Fehlernummer" und die Nummer irgendwo anders zuweise.
    "Fehlernummer" soll nur einmal drinstehen...sonst würde tausensmal "Fehlernummer xxx" drinstehen.



  • Mondmann schrieb:

    ...
    Übergebe ich wahllos Fehlernummmer, verliere ich irgendwann den Überblick und es kann sein, daß die eine oder andere 2 und 3mal vorkommt....

    Das klingt nach "Konzeptmix". Wenn ich das richtg verstanden habe, willst Du

    • einen Teil der Fehlernummern (mit Texten versehen) in einem Konfigfile hinterlegen und
    • einen anderen Teil fest im Source verdrahten ...

    ... aber diese beiden Quellen sollen gleichzeitig unabhängig von einandern und trotzdem schnittmengenfrei sein.

    Das wird so nicht klappen - für eins von beiden musst Du Dich schon entscheiden.
    ich würde raten, die Fehlernummern frei im Programm zu vergeben und die Stringzuordnung unabhängig davon zu machen.
    Eine eindeutige (und doch reproduzierbare) Vergabe der Nummern kann man in eine eigene Funktion kapseln, die aus "Quelleninformationen" (File-, Klassen-, Funktionsname, Zeilennummer, Position, ...) eine Zahl zusammenbaut.
    Spätestens beim Durchlauf des Programms sieht man dann, welche Fehlernummern kommen und für welche davon Du welche Texte in Deinem File hinterlegen möchtest.

    hmmm war das einigermaßen klar, was ich meinte ?

    Gruß,

    Simon2.



  • hm, ja ist (denk ich ) klar.

    Ich hinterlege also die Texte und übergebe der Funktion den Index des Textes.

    Als Fehlernummer generiere ich eine einmalige Zahl.
    Ich denke für mich, daß das Modul als Nummer und die Zeilennummer einmalig genug sein sollten.

    Also ich habe zB.
    fkt1.cpp -> 100
    fkt2.cpp -> 200
    fkt3.cpp -> 300
    ....

    So habe ich dann Fehlernummern im Stil: 200:2345, 300:1000, 300:7893
    usw...

    haste das so gemeint?



  • wir verwenden hier ein schema mit einem 16byte wert, dabei gelten die ersten 4 byte für die andwendung 4 byte für die fehler art (fehler-icon, notify icon, ... ja ich weis 4 byte sind übertrieben) 4 byte fürs modul und 4 byte für die fehlernummer

    per define kann dann eine fehlerID erzeugt werden

    #define ERROR_MOD_A_SOCKET_CREATION_FAILED  (MYAPP_MAKRO |   ICON_ERROR   |   MOD_A_MAKRO   | 0x0001)
                                        0x0000000000000010   | 0x000000000004 |   0x00000005  
                                        0x0001000500040011 als einmalige fehlerID
    

    für die fehlermeldungen kannst du dir ein array anlegen aus paaren von int und string welche du dann einfach in einer map abhandelst.

    vielleicht ist das ein anreiz

    PS die fehlertexte kannst du dann ja falls nötig auch in irgendeiner form kategorisieren



  • Hallo CStoll,woher bekomme ich denn den lexical_cast?
    Der kennt mein compiler nicht:-)

    Ceos: Dein BEispiel klingt auch sehr interessant.
    werde erstmal das von CStoll ausprobieren, dann Deines.

    Viele grüße Mondmann



  • Boost (oder du guckst dir die FAQ zum Thema "Einmal Zahl nach String und zurück" an, um Alternativen dazu zu finden).



  • Ach Boost...alles klar werd ich mir mal reinziehen...Grüße Mondmann



  • Ok das Boost Teil ist cool:-)

    Ich zeit Euch jetzt wie ichs gemacht habe:

    Also.
    Ich habe die Funktion von CStoll genommen und noch etwas angepasst:

    string FKT_error(char* fehlercode,int zeile)
    {
    //Fehlercode max 6
    //0-3= fehlernummer
    //4-5 Modulnummer
    
    string fehler_anzeige;
    
    char lesemap[5];
    char lesemodul[3];
    
    //Fehlernummer aus map
    strncpy(lesemap,fehlercode,4);
    lesemap[4]='\0';
    UINT num=atoi(lesemap);	
    
    //Modulnummer
    lesemodul[0]=fehlercode[4];
    lesemodul[1]=fehlercode[5];
    lesemodul[2]='\0';
    
      map<int,string>::iterator pos = error.find(num);
      if(pos!=error.end())
      {
    	  fehler_anzeige=pos->second;
    	  fehler_anzeige+="-";
    	  fehler_anzeige+=lesemodul;
    	  fehler_anzeige+="-";
    	  fehler_anzeige+=lexical_cast<string>(zeile);
    	  return fehler_anzeige;
      }
      else
        return default_fehler + " ("+lexical_cast<string>(num)+")";
    }
    

    _zeile ist hierbei per #define das Makro __LINE__

    Der Aufruf sieht so aus:

    FKT_logausgabe("000213",_zeile);
    
    oder 
    
    FKT_logausgabe("005804",_zeile);
    

    Das 1 Argument baut sich folgendermaßen auf:
    zb: "000213"

    0002 : Fehlertext der aus der map gelesen wird
    13: Dies ist die Modulnummer, also zb. "main.cpp"

    Die Ausgabe sieht nachher so aus:

    Fehlernummer 13-1344

    oder

    Kommunikationsfehler 04-499

    usw.

    Ich habe also einen Text und eine einmalige Fehlernummer aus Moduldefinition und Zeilennummer.
    Die Fehlernummer kann somit maximal 9999 sein, was ich im Leben nie brauchen werde.

    Nicht schlecht, was?

    Achja meine map sieht so aus:

    /* 0-09 */
    error[0]=	"Unbekannter Fehler";
    error[1]=	"Fehler beim Laden von wsterm.ini, Vorgang wird abgebrochen.";
    error[2]=	"INI Datei wurde gelesen";
    error[3]=	"HANDSHAKE aktiviert";
    error[4]=	"Fehlernummer ";
    error[5]=	"DLL wurde geladen und ordnungsgemäß initialisiert";
    error[6]=	"";
    error[7]=	"";
    error[8]=	"";
    error[9]=	"";
    
    /* 10-19 */
    error[10]=	"Willkommen bei PEP...";
    error[11]=	"";
    error[12]=	"";
    error[13]=	"";
    error[14]=	"";
    error[15]=	"";
    error[16]=	"";
    error[17]=	"";
    error[18]=	"";
    error[19]=	"";
    

    Ich habe das Ganze noch für eine Log-Funktion die Erfolgsmeldungen aus derselben Map ausliest - ohne Fehlernummmer.

    Für Anregungen, Verbesserungen bin ich dankbar.

    Grüße Mondmann


Anmelden zum Antworten