string frage



  • Mach eine simple log-Datei, die du dann mit Stream-Operatoren fütterst. Geht einfach und ist jederzeit nach dem Programmende lesbar.

    #incluse <fstream.h>          // Deklarationen
    #include <iomanip.h>
    #include <iostream.h>
    
    ofstream log;                 // Stream festlegen  
    
    log.open("LOGFILE.LOG");      // log-Datei anlegen zum Programmstart
    log.setf(ios::fixed);         // Stream-Manipulatoren für float / double 
    log.setf(ios::floatfield);    // festlegen
    log.setf(ios::showpoint);
    
    log << "Ein integer    " << intValue    << "  ist geloggt" << endl;
    log << "Ein double     " << doubleValue << "  ist geloggt" << endl;
    
    log.close();                  // log-Datei schliessen zum Programmende
    

    Ich benutze diesen Weg für alle Programmentwicklungen zur Protokollierung, was im Programm geschieht und espare mir damit oft aufwendiges debug. Statt wie hier
    intValue und doubleValue kannst du auch deine Funktion GetIndex() einsetzen.



  • berniebutt schrieb:

    #include <fstream.h>
    #include <iomanip.h>
    #include <iostream.h>
    

    Diese Header gibt es im C++-Standard nicht.



  • rotondo schrieb:

    wie wäre es hier mit ?

    #include<iostream>     
    using namespace std;
    
    void logThis(string a,int x, string b)
    { cout<<a<<x<<b; }
    main()
    {
    
    logThis("Nach ",2," Bier nicht mehr fahren!");
    
    }
    

    Er will doch was Dynamisches und nicht immer genau einen string, ein int und noch einen string loggen... 🙄



  • Das macht man mit boost so:

    logThis("Ein Satz " + lexical_cast<string>(getIndex()) + " wird geloggt\n");
    

    Und ohne boost solltest du eine Art lexical_cast selbst implementieren oder nach VCL-Art Funktionen wie IntToStr und DoubleToStr implementieren.



  • Athar schrieb:

    Das macht man mit boost so:

    logThis("Ein Satz " + lexical_cast<string>(getIndex()) + " wird geloggt\n");
    

    Und ohne boost solltest du eine Art lexical_cast selbst implementieren oder nach VCL-Art Funktionen wie IntToStr und DoubleToStr implementieren.

    Operation geglückt, Patient tot. Schlagzeile morgen: Spatz von Kanone erschossen.
    Findest das nicht n bissle Overkill, dem Ganzen jetzt gleich mit lexical_cast beizukommen?



  • krümelkacker schrieb:

    berniebutt schrieb:

    #include <fstream.h>
    #include <iomanip.h>
    #include <iostream.h>
    

    Diese Header gibt es im C++-Standard nicht.

    Stimmt nicht, sonst könnte man die Stream-Klassen von C++ nicht einsetzen! Steht so explizit auch in meinen Compiler-Beschreibungen. Mir erscheint mein Vorschlag einfacher und besser als die sonst hier vorgeschlagenen Frickeleien.



  • berniebutt schrieb:

    krümelkacker schrieb:

    berniebutt schrieb:

    #include <fstream.h>
    #include <iomanip.h>
    #include <iostream.h>
    

    Diese Header gibt es im C++-Standard nicht.

    Stimmt nicht, sonst könnte man die Stream-Klassen von C++ nicht einsetzen!

    Die Streamklassen aus dem Standard befinden sich in <fstream>, <iomanip> und <iostream>, ohne .h am Ende. die genannten Header werden allerdings AFAIK im Standard erwähnt und als veraltet gekennzeichnet, IIRC müssen Compiler sie daher nciht mehr unterstützen.



  • Ich würde wahrscheinlich eine Logger-Klasse bereitstellen, die intern einen Stream besitzt und den operator<< anbietet (als Funktionstemplate). Somit kann man im C++-Stil loggen, die Werte werden an den Stream weitergeleitet.

    Jetzt etwas hinzufrickeln, nur damit man unbedingt + benutzen kann, halte ich nicht für sinnvoll. Wir sind schliesslich nicht in Java.



  • pumuckl schrieb:

    Operation geglückt, Patient tot. Schlagzeile morgen: Spatz von Kanone erschossen.
    Findest das nicht n bissle Overkill, dem Ganzen jetzt gleich mit lexical_cast beizukommen?

    Durchaus nicht, lexical_cast ist hier genau das passende Mittel. lexical_cast hat auch eher die Schlagkraft eines Federballs, davon wird der Spatz schon nicht umkommen.
    Die Variante ist sogar geringfügig einfacher als einen operator<< anzubieten, jedenfalls wenn die Logeinträge einen obligatorischen Header haben müssen (Zeitstempel, Thread-/Client-/...-ID...).



  • Athar schrieb:

    Durchaus nicht, lexical_cast ist hier genau das passende Mittel.

    Nein.

    Athar schrieb:

    Die Variante ist sogar geringfügig einfacher als einen operator<< anzubieten

    Und auch geringfügig einfacher zu verwenden, oder?

    Log("Bild Nummer " + lexical_cast<std::string>(number) + " geladen (Grösse " + lexical_cast<std::string>(image.GetWidth()) + "x" + lexical_cast<std::string>(image.GetHeight()) + ")");
    

    vs.

    Log << "Bild Nummer " << number << " geladen (Grösse " << image.GetWidth() + "x" + << image.GetHeight() << ")";
    

    Athar schrieb:

    jedenfalls wenn die Logeinträge einen obligatorischen Header haben müssen (Zeitstempel, Thread-/Client-/...-ID...).

    Dafür kann man einen speziellen Wert einrichten, sowas wie std::endl . Wenn man sonstige Formatierungen einrichten möchte (z.B. neuer Absatz, Untertitel oder irgendwas), ist man wiederum flexibler mit dem Stream-Operator. Andererseits geht natürlich auch etwas in der Art:

    Log.Flush();
    


  • Wieso nicht einfach std::clog nutzen? Das ist genau dafür gemacht. Nix eigener Stream oder operator<< überladen.

    > oder nach VCL-Art Funktionen wie IntToStr und DoubleToStr implementieren.

    Bloß nicht. Zum Glück gibt's das nicht im Standard-C++.

    > Mir erscheint mein Vorschlag einfacher und besser als die sonst hier vorgeschlagenen Frickeleien.

    Einen Streampuffer zu wechseln ist absolut keine Frickelei.



  • Ad aCTa schrieb:

    > Mir erscheint mein Vorschlag einfacher und besser als die sonst hier vorgeschlagenen Frickeleien.

    Manche mögen Dinge eben kompliziert und wollen alles nutzen, was C++ so bietet. Es geht nur um Streams und die kann man direkt mit was auch immer beschicken und entscheiden, wo die Ausgaben landen sollen. Alle Frickeleien sind suspekt und damit entbehrlich. Ich verstehe nicht, warum man sich um so etwas überhaupt Gedanken macht. Man macht das so nebenbei. Gehört zum Handwerkszeug der Programmierung.
    daddeldu :p



  • > und die kann man direkt mit was auch immer beschicken und entscheiden, wo die Ausgaben landen sollen. Alle Frickeleien sind suspekt und damit entbehrlich.

    Au weia. Streams und Buffer sind absolut keine Frickeleien. std::clog auch nicht.

    > Ich verstehe nicht, warum man sich um so etwas überhaupt Gedanken macht.

    Dann solltest du dir lieber über dieses Thema ein paar Gedanken machen, am besten mit dem Struppi, der erläutert das recht schön.



  • hi leute,

    also interessante diskussion, auch wenn ich nur die hälfte der details verstehe 😉 ich habe es über ein satz macros gelöst, nicht wirklich schön, ging aber schnell. danke euch.



  • Ad aCTa schrieb:

    Dann solltest du dir lieber über dieses Thema ein paar Gedanken machen, am besten mit dem Struppi, der erläutert das recht schön.

    Ist Struppi dein Hund - wie soll ich ihn fragen und weiss der was vom Programmieren? Hier scheint es wieder einmal eine heisse Diskussion zu geben, ob nur pures C++ oder für einfache Dinge auch mal schlicht mit ANSI-C gemacht. Schliesst sich ja nicht aus. Man macht das einfach und fertig! Zum letzten Beitrag des Fragestellers: Macros würde ich hier nicht einsetzen.
    Thema für mich: daddeldu 🙄



  • berniebutt schrieb:

    Ist Struppi dein Hund - wie soll ich ihn fragen und weiss der was vom Programmieren?

    Dieser Hund hat immerhin die Sprache erfunden.

    Hier scheint es wieder einmal eine heisse Diskussion zu geben, ob nur pures C++ oder für einfache Dinge auch mal schlicht mit ANSI-C gemacht.

    Wo ist hier bitte eine C-Lösung?



  • berniebutt schrieb:

    Zum letzten Beitrag des Fragestellers: Macros würde ich hier nicht einsetzen.
    Thema für mich: daddeldu 🙄

    Natürlich setzt man fürs Logging ein Makro ein. Aus dem selben Grunde, aus dem man für assert ein Makro verwendet.



  • Ich hab mir zum debuggen und loggen neulich was realtiv simples geschrieben:

    class Log
    {
      static ostream& instance(std::string const& name = "mylog.log")
      {
        static std::ofstream of(name.c_str());
        return of;
      }
    public:
      static void init(std::string const& name)
      {
        (void*)instance(name);
      }
    
      static ostream& log()
      {
        return instance();
      }
      static ostream& debug()
      {
      #ifdef _DEBUG
        return instance() << "DBG:>>> ";
      #else
        static struct dummyostream : public std::ostream
        {
          template <typename T> dummyostream& operator<< (T const&) {return *this;}
        } os;
        return os;
      #endif
      }
    };
    
    int main()
    {
      Log::init("optionalalternativername.log");
      Log::log() << "alles ok" << endl;
      Log::debug() << "Zeile " << __LINE__ << " erreicht";
    }
    


  • volkard schrieb:

    Natürlich setzt man fürs Logging ein Makro ein. Aus dem selben Grunde, aus dem man für assert ein Makro verwendet.

    Nur wenn man das Logging per PP-Flag komplett ausschalten will UND bereit ist dafür auf variable Parameterzahlen und den ganzen Kram zu verzichten bzw. sich den Output dann doch irgendwie wieder irgendwie on the Fly zusammenschustert.



  • pumuckl schrieb:

    UND bereit ist dafür auf variable Parameterzahlen und den ganzen Kram zu verzichten bzw. sich den Output dann doch irgendwie wieder irgendwie on the Fly zusammenschustert.

    #ifdef DEBUGGE_DU_SAU
    #define debug(msg) cout << (msg);
    #else
    #define debug(msg);
    #endif
    

    Oder so ähnlich. Schön ist das natürlich nicht, widerlegt aber deine Aussage.


Anmelden zum Antworten