String einen substring über mehrere Zeilen



  • @kritticker, SeppJ: Ihr solltet wirklich über die Sache streiten, nicht über Euch. Ich habe das Gefühl, dass Ihr einfach eine andere Sichtweise darüber habt, wie ein Fehler aus einer Ini-Datei (falsches Format etc.) zu klassifizieren ist.

    kritticker sieht " logic_error "s explizit als solche an, die aus der Programmlogik kommen; die Ini-Datei dagegen sieht er auf der Ebene von Benutzereingaben, daher kann es (da das Programm selbst perfekt ist) per Definition von "logic_error" (errors presumably detectable before the program executes) kein solcher sein.

    Prinzipiell sehe ich das ähnlich, würde in diesem Fall eher ein " runtime_error " verwenden oder eine eigene Klasse, davon abgeleitet, sowas in der Art "user_input_error" oder "bad_config_error"...



  • An std::logic_error ist technisch nichts auszusetzen, wer für sich allein programmiert, soll den ruhig verwenden, wie er will.

    Sofern allerdings jemand anders den Code anschaut, sollte man sich an gewisse allgemein anerkannte Konventionen halten. Was im Standard steht ist allgemein anerkannt. Wenn der Standard unsinnig ist, soll es nicht verwendet werden.

    SeppJ schrieb:

    Mir doch egal, dass es nicht durch einen internen Fehler geschehen ist (natürlich passiert so etwas nicht durch interne Fehler, meine Programme sind schließlich richtig).

    Es ist nur so, dass jeder andere Programmierer logic_error als internen Fehler ansieht. Die Klasse umzudeuten halte ich für nicht so klug. Wenn dir "logischer Fehler" gefällt, leite dir halt eine Klasse logic_input_error von std::runtime_error ab.

    Ich persönlich meine, dass ios::failure genau dieses Flavour (fehlerhafter User-Input) ausdrückt. Die genaue Fehlernachricht steht für den, der sie wissen möchte in einem separaten Parameter.



  • Noch ein paar allgemeine Fragen:

    @ Helppls1234: Wie fix ist denn Dein Dateiformat? Das Ini-Format, was ich so kenne, braucht eigentlich keine schließenden Tags. Es enthält "Sections" (das in den eckigen Klammern) und dahinter Key-Value-Paare, bis zur nächsten Section oder Dateiende. Deine Datei wäre dann z.B.:

    `[Schurke]

    Str=12

    Dex=17

    Int=4

    [Krieger]

    Str=18

    Dex=10

    Int=2`

    Das würde den Parser etwas vereinfachen...

    @ SeppJ: Warum gibst Du bei den get -Methoden nicht einfach den Wert zurück? Schon klar, Template-Typ muss in die Signatur, aber irgendwie fühlt es sich komisch an, bei einem get() den Wert als Referenz zu übergeben und die Möglichkeit eines Rückgabewertes durch void zu verschenken.

    Bei einer Ini-Datei würde ich aus dem Bauch raus die Values entweder fix als string zurückgeben (und die Interpretation nach int oder double später; der Parser soll ja den Typ der einzelnen Values gar nicht kennen müssen), oder gerne die Templates so wie sie sind und dann speziell einen anderen Typ anfordern.

    Also statt:

    int a;
    sip.get_verbose(std::cout, "Krieger", "Str", a);
    

    etwa so:

    int a = sip.get_verbose<int>(std::cout, "Krieger", "Str");
    

    @Sone: Warum nicht einfach ein vector aus shared_ptr ? Bei Containern aus puren Pointern (und den dazugehörigen selbstgeschriebenen Lösch-Schleifen) krieg ich inzwischen Gänsehaut). Also statt

    std::vector<Node*> child_nodes; // Darf *nicht* verändert werden - Inhalt wird gelöscht
    
        ~Node()
        {
            std::for_each( std::begin(child_nodes), std::end(child_nodes), static_cast<void(*)(void*)>(operator delete) );
        }
    
    std::vector<std::shared_ptr<Node>> child_nodes; // Darf *nicht* verändert werden - Inhalt wird gelöscht
    


  • @SeppJ

    isoiec14882 19.1.1 - 1 schrieb:

    The class logic_error defines the type of objects thrown as exceptions to report errors presumably detectable before the program executes, such as violations of logical preconditions or class invariants.

    Für mich bedeutet das: man muss ein Programm so schreiben können dass es keine logic_error wirft.
    Im Falle von fehlerhaften Input-Files würde das bedeuten dass man das File erstmal selbst verifizieren müsste bevor man es dem Parser füttern darf.
    Was sinnlos ist.

    => Der Parser sollte keine logic_error werfen.

    Ich kenne übrigens auch keinen Programmierer der das anders interpretiert.


  • Mod

    minastaros schrieb:

    @ SeppJ: Warum gibst Du bei den get -Methoden nicht einfach den Wert zurück? Schon klar, Template-Typ muss in die Signatur, aber irgendwie fühlt es sich komisch an, bei einem get() den Wert als Referenz zu übergeben und die Möglichkeit eines Rückgabewertes durch void zu verschenken.

    Damit man den Typ nicht angeben braucht, sondern die automatische Templateparametererkennung nutzen kann.



  • SeppJ schrieb:

    minastaros schrieb:

    @ SeppJ: Warum gibst Du bei den get -Methoden nicht einfach den Wert zurück? Schon klar, Template-Typ muss in die Signatur, aber irgendwie fühlt es sich komisch an, bei einem get() den Wert als Referenz zu übergeben und die Möglichkeit eines Rückgabewertes durch void zu verschenken.

    Damit man den Typ nicht angeben braucht, sondern die automatische Templateparametererkennung nutzen kann.

    Einerseits das, andererseits funktioniert das auch im pathologischen Fall, wenn der Typ keinen Default-Konstruktor hat. Dieses get() ist richtig.

    Was ich allerdings nicht ok finde, ist die Schwesterfunktion

    template<typename T> void get(std::string const& category, std::string const& name,
                                    T &entry, const T& default_value) const
      {
        try
          {
            get(category, name, entry);
          }
        catch (std::logic_error)
          {
            entry = default_value;
          }
      }
    

    Manche (mich eingeschlossen) würden diese Nutzung von Exceptions als "premature Pessimization" beschreiben.

    Dazu kommt:
    - "Throw by value, catch by reference" -- hier nicht schlimm, aber grundsätzlich schlechter Stil
    - Bei normalen Ini-Dateien gilt: Fehler ausgeben bei fehlerhaftem Wert, Defaultwert bei fehlender Angabe, sonst der angegebene Wert. Für dieses get() wird "kein Wert" und "falscher Wert" gleich behandelt. Womöglich wieder eine bewusste Entscheidung!?

    hustbaer schrieb:

    => Der Parser sollte keine logic_error werfen.

    Schön, dass ich nicht der einzige bin, der das so sieht.


  • Mod

    kritticker schrieb:

    Womöglich wieder eine bewusste Entscheidung!?

    Nein, in allen drei Fällen Faulheit. Eine Defaultwertfunktion war lauf Aufgabenstellung verlangt. Durch Mitnutzung der normalen get-Funktion, konnte ich mir so die Codewiederholung sparen. Das get ist nicht Kernteil dessen gewesen, was ich vorführen wollte.



  • Und der Code-Blah ist einfach überwältigend.

    Supi! Sollte es auch sein. Ein möchtegern-Perfektionist wie ich...

    Hier der optimierte Code.
    http://ideone.com/lNJGDO


  • Mod

    Wow, mein Rechner setzt erst einmal eine Sekunde aus, wenn er den Tab mit dem Quelltext lädt 😮 .



  • SeppJ schrieb:

    Wow, mein Rechner setzt erst einmal eine Sekunde aus, wenn er den Tab mit dem Quelltext lädt 😮 .

    Langsamer Rechner, nicht wahr?

    Hier die Geschwindigkeiten, die ich gemessen habe:

    Kritticker: 3547000 
    Sone:       1210000
    SeppJ:      710000
    

    Verdammt, da hat der SeppJ aber Schwein. Nur weil ich so viel drumherum habe.


  • Mod

    Das ist kein Glück. Was erwartet ihr denn von solch fetten Codes? Gerade die Regex von Kritticker sind Overkill³. Bei dir kann man wenigstens sagen, dass dein Code mehr kann.



  • Ich glaube es ist schlechter Stil die Exceptions einfach nur mit einem englischen Text zu beschreiben. Was ist, wenn das Programm mal im Ausland läuft. 🙄



  • Nun, wenn eine Bibliothek mir Exceptions entgegenwirft, nur weil sie mit ein paar falschen Eintraegen konfrontiert wird, dann wuerde ich die Bibliothek wechseln.

    Supi! Sollte es auch sein. Ein möchtegern-Perfektionist wie ich...

    Code sollte einfach sein.



  • Ich hätte einfach ne XML & nen einfachen XML Parser wie irrXML genommen...



  • Es ist grundsaetzlich falsch, die Worte 'einfach' und XML in einem Satz zu sagen. 🙂



  • knivil schrieb:

    Es ist grundsaetzlich falsch, die Worte 'einfach' und XML in einem Satz zu sagen. 🙂

    Wieso? Man brauch nicht für jeden Furz nen Xercxes Parser und andere Späße mit tausendfacher DOM Validierung und ähnlichem Kram.
    Manchmal ist weniger einfach mehr.
    irrXML ist schnell, einfach. Kann dafür wenig.
    Aber solange man nur lesen will und nicht validieren, sehe ich daran nichts falsches.



  • Habe ich von irrXML als Bibliothek gesprochen? Nein!

    PS: Habe gerade irrXML-Api ueberflogen. Sorry, im Vergleich zu anderen XML-Gedoens ist es vielleicht leichtgewichtig, aber im Vergleich zu ini-Parser oder JSON-Parser trotzdem Schwergewicht. Es ist auch schwer zu sagen, wie fehlertolerant irrXML ist. Bei ini-Files sehr einfach zu bewerkstelligen, naja, ausser Sones Implementierung, die mit Exceptions um sich wirft.



  • Man kann natürlich auch JSON nehmen. Mir wayne. Mir gings nur darum, dass man lieber auf bewährte Dinge setzen sollte als sich das Leben unnötig schwer zu machen.



  • was anderes schrieb:

    Ich glaube es ist schlechter Stil die Exceptions einfach nur mit einem englischen Text zu beschreiben. Was ist, wenn das Programm mal im Ausland läuft. 🙄

    Exceptions zu übersetzen ist natürlich die ganz tolle Idee. 🙄

    Darf ich fragen was du mit deinem Beitrag sagen willst?



  • hustbaer schrieb:

    was anderes schrieb:

    Ich glaube es ist schlechter Stil die Exceptions einfach nur mit einem englischen Text zu beschreiben. Was ist, wenn das Programm mal im Ausland läuft. 🙄

    Exceptions zu übersetzen ist natürlich die ganz tolle Idee. 🙄

    Darf ich fragen was du mit deinem Beitrag sagen willst?

    Ich wollte damit einfach nur sagen das der Exception-Text im UI-Layer zusammengebaut werden sollte. Die Exception-Klasse sollte alle Informationen dazu beinhalten, aber nicht den Text selbst. 😉


Anmelden zum Antworten