variable parameterliste und vsprintf/vasprintf



  • hallo!

    ich habe eine methode die sich ähnlich verhält wie ein printf, sprich man kann diese genau so bedienen wie ein printf und der erzeugte text-value wird dann intern für div. sachen verwendet (log-files, wird intern an div. services gesendet übers netzwerk, usw.)

    nun hab ich den fall, dass ich den erzeugten wert gerne als stl string/stringstream weiterverwenden möchte, wie stelle ich das an, dass hier nicht zweimal speicher reserviert wird?

    beispiel 1:

    void bsp1::logInfo (const char *msgtext, ...)
    {
    
        TEXT msg [1000];
        string msgstr;
    
        va_list arg_ptr;
        va_start (arg_ptr, msgtext);
        vsnprintf(msg, sizeof(msg)-1, msgtext, arg_ptr); 
        va_end (arg_ptr);
    
        msgstr = msg;
        ..................
    
    }
    

    beispiel 2:

    void bsp2::logInfo (const char *msgtext, ...)
    {
    
        TEXT *msg(null);
        string msgstr;
    
        va_list arg_ptr;
        va_start (arg_ptr, msgtext);
        vasprintf(&msg , msgtext, arg_ptr); // ist compiler abhaenging!!!
        va_end (arg_ptr);
    
        msgstr = msg;
        ..................
    
    }
    

    wenn man nun diese methode öfters aufruft, verschleudert man meiner meinung nach zuviele recourcen. also wie könnte man es besser machen?
    und dabei möchte ich nicht mit char-pointern arbeiten, sondern doch die vorteile eines stl strings oder stringstreams genießen 🙂

    danke für eure hilfe!



  • taff schrieb:

    und dabei möchte ich nicht mit char-pointern arbeiten, sondern doch die vorteile eines stl strings oder stringstreams genießen 🙂

    Wenn das so ist, warum dann nicht gleich richtig? C++'s IOStreams bieten ihre eigene Methode zur Datenausgabe (über op<<) an - die solltest du eventuell verwenden.

    (Ich weiß nicht genau, ob's passt - aber boost::Format wäre auch ein Ansatz)



  • problem besteht für mich darin, dass alles printf-like sein sollte bei der parameter übergabe, wie soll ich dann dies mittels dem op<< in diese form bringen?
    den msgtext selbst durchparsen und alle kombinationen zb. "3d %-20.20s %17lu" selbst auswerten und den parameter von der parameterliste somit richtig formatieren usw.? 😕

    leider kann ich boost nicht verwenden, leider 😞



  • taff schrieb:

    problem besteht für mich darin, dass alles printf-like sein sollte bei der parameter übergabe, wie soll ich dann dies mittels dem op<< in diese form bringen?

    Hat dir schon mal jemand gesagt, wie unsicher und fehleranfällig der scanf()-Ansatz (und variable Parameterlisten im Allgemeinen) ist? Wenn du die Chance hast, mach einen großen Bogen darum.

    Ansonsten kommst du wohl um das Umkopieren nicht herum - std::string liefert dir aus gutem Grund keinen veränderbaren char-Pointer auf seine Daten.

    ---

    Das folgende ist auf eigene Gefahr: ⚠
    Wenn du unbedingt willst, kannst du über const_cast<char*>(msg.c_str()) oder &str[0] auf dein Zeichen-Array zugreifen. Aber sorg bitte vorher dafür, daß der String dort genug Platz hat.



  • also, die fehleranfälligkeit ist mir nicht ganz so bekannt, aber vielleicht könntest du mir ja eine gute quelle zeigen wo ich das nachlesen kann.

    ein problem ist einfach, dass mittels printf ein %-20.20s "kompakter" ist als, wenn man dies mittels einem stringstream nachprogrammieren muss.
    weiteres problem ist auch, dass in der firmen internen lib es leider "standard" ist, dass es solche parameter listen mit printf-like sachen gibt. 😞

    also die cast sache mit std::string ist mir zugefährlich.



  • taff schrieb:

    also, die fehleranfälligkeit ist mir nicht ganz so bekannt, aber vielleicht könntest du mir ja eine gute quelle zeigen wo ich das nachlesen kann.

    Probier einfach mal aus, was bei einem "printf("%d");" oder "int i=1;printf("%f",i);" herauskommt. Im Klartext: Niemand kann überprüfen, ob die an printf() übergebenen Argumente mit dem Formatstring übereinstimmen, also führt C beim Compilieren nur ein paar Standard-Umwandlungen durch und vertraut ansonsten darauf, daß du weißt, was du dort übergibst.

    PS: Ja, Streams sind etwas komplizierter zu handhaben, aber dafür sicherer (im Gegensatz zu printf() WISSEN sie, was für einen Typ sie bekommen, und wie sie damit umgehen müssen).



  • wenn du weniger fehleranfällige formatstings brauchst kann ich boost::format empfehlen

    format x("%2d, %2d")
    
    cout << x % 1 % 3 << x % 3 % 4;
    


  • CStoll schrieb:

    Im Klartext: Niemand kann überprüfen, ob die an printf() übergebenen Argumente mit dem Formatstring übereinstimmen, also führt C beim Compilieren nur ein paar Standard-Umwandlungen durch und vertraut ansonsten darauf, daß du weißt, was du dort übergibst.

    ok, dann dürfte ich mir selbst keine listen bauen usw. also irgendwie muss man schon wissen was man macht. jedoch ist auch mir klar, dass sich bei einem printf ungewollte fehler einschleichen können und eben dann nicht von "selbst" gelöst werden wie bei einem stream.

    r0nny schrieb:

    wenn du weniger fehleranfällige formatstings brauchst kann ich boost::format empfehlen

    würde ich gerne, leider nicht möglich/erlaubt (firmen-lib 😡 )

    fazit: danke für eure hilfe, aber wie ihr seht sind mir teilweise die hände gebunden und ich muss wohl mein problem mit einem char* lösen anstatt mit einem std:string 😞


Anmelden zum Antworten