Funktion mit beliebigen Argumenten



  • hi

    In C/C++ gibt es ja Funktionen mit beliebig vielen und beliebig gearteten Argumenten. So z.B. die sprintf() Funktion. Ich möchte nun gerne eine Funktion schreiben, die auch beliebige Argumente arhalten kann und diese möchte ich an die sprintf() Funktion wieterleiten. Wie geht das?

    Marvin


  • Mod

    Hier findest du eine Referenz für alles was du dafür brauchst:

    http://www.cplusplus.com/reference/clibrary/cstdarg/

    Ob das jedoch sinnvoll ist, ist eine andere Frage, schließlich kann man das in C++ mittels Operatorüberladung viel sauberer lösen.



  • Vielen Dank für die Antwort. Wie geht denn das mit Operatorüberladung? Und was hat das mit Operatoren zu tun? Wäre toll, wenn ich das geschickter lösen könnte, denn mit der va_arg-Lösung wäre ich ja gezwungen, zunächst die Werte zu sammeln und dann über eine dicke Fallunterscheidung (switch) je nach Anzahl der Argumente die unterliegende Funktion speziell aufzurufen. Die Lösung wäre also nicht wirklich dynamisch.

    Marvin



  • Nur Info, wie ich mir das ungefähr vorstelle:

    void log( const char* string, ... )
    {
        FILE* f;
        fopen( &f, "filename.log", "a" );
        fprintf( f, string, <übergenene Argumentenliste> );
        fclose( f );
    }
    




  • Dabei aber aufpassen, dass nur PODs in der variablen Argumentliste stehen dürfen. Wenn du einen C++0x Compiler hast, bieten sich hier Variadic Templates an.


  • Mod

    Qudus schrieb:

    Vielen Dank für die Antwort. Wie geht denn das mit Operatorüberladung? Und was hat das mit Operatoren zu tun? Wäre toll, wenn ich das geschickter lösen könnte, denn mit der va_arg-Lösung wäre ich ja gezwungen, zunächst die Werte zu sammeln und dann über eine dicke Fallunterscheidung (switch) je nach Anzahl der Argumente die unterliegende Funktion speziell aufzurufen. Die Lösung wäre also nicht wirklich dynamisch.

    Marvin

    Wenn die Funktion das machen soll, was dein Beispiel demonstriert, warum nimmst du dann nicht einfach C++ Datei Ein-/Ausgabe? Erläutere mal, was genau dein Ziel ist, dann kann dir gezielter geholfen werden.



  • Vielen Dank nochmal for die Antworten. Ich denke, jetzt bin ich im Bilde.

    Ich habe wohl nicht genug darüber nachgedacht. Die Unterscheidung, wieviele Parameter übergeben wurden, muss ich in manchen Fällen sowieso machen. Daher werde ich beide Lösungen gebrauchen können.

    Ich kann die C++ Datei Ein-/ausgabe nicht einfach verwenden, weil das bedeuten würde, dass ich an jeder Stelle, an der ich eine log-Ausgabe machen will, die Datei öffnen, den Dateinamen exponieren und die Datei auch wieder schließen müsste. Wenn ich die Datei dauerhaft geöffnet lasse, riskiere ich, dass die wichtigste Ausgabe - nämlich die bei einem Crash - verloren geht.

    Was ich vorhabe, ist ziemlich genau das, was ich vorhin als Beispiel geschrieben habe, allerdings in verschiedenen Ausprägungen und noch mit einer Statusabfrage, ob das Logging System bereits initialisiert ist.

    Ich verwende übrigens den Compiler der Visual C++ 2005 Express IDE.

    Wenn meine Fragen manchmal etwas blöd erscheinen (oder sind ;)), liegt das daran, dass ich aus der Java Welt komme und mich nur (zähneknirschend) mit dem Bisschen C/C++ rumschlage, was ich minimal brauche.

    Marvin



  • Qudus schrieb:

    Ich kann die C++ Datei Ein-/ausgabe nicht einfach verwenden, weil das bedeuten würde, dass ich an jeder Stelle, an der ich eine log-Ausgabe machen will, die Datei öffnen, den Dateinamen exponieren und die Datei auch wieder schließen müsste.

    Das machst du auch bei deiner Logfunktion. Und wenn du ohnehin mit einer Variablen Parameterliste arbeitest kannst du ebenso einen stringstream verwenden, diesen zusammensetzen und an eine Logfunktion übergeben...

    Aber das ist nur meine Meinung: tue einfach was du meinst. Wenn du jedesmal aufs neue die Datei öffnest hast du jedenfalls ganz ähnliche Probleme (1. ist dies langsam, 2. kann der Dateizugriff fehlschlagen...). Ich bezweifel das die Loggingbibliotheken von Java jedesmal neue Dateien öffnen.


  • Mod

    Also das klingt eigentlich nach einem Fall für eine Loggingklasse, wenn du das wirklich mit dem immer wieder öffnen/schließen machen willst.

    Zwei andere Vorschläge:
    Ganz einfach: cerr verwenden und Fehlerausgabe des Betriebssystems in Datei umlenken.

    Etwas komplexer: Einen ungepufferten ostream mit einer Datei verbinden. Ich weiß jetzt nicht, wie das geht, aber ich bin mir sicher, dass es geht. Vor einiger Zeit gab es da mal einen thread zum Erben von streambuf, da könnte die nötige Information zu finden sein. Oder nochmal im Forum fragen, es findet sich bestimmt ein Experte für streams.



  • asc schrieb:

    Das machst du auch bei deiner Logfunktion.

    Da habe ich mich wohl missverständlich ausgedrückt. Natürlich wird in meiner Funktion genauso jedesmal eine Datei geöffent. Aber der Vorteil ist, dass ich in meinem sonstigen Coding nur eine einzige Zeile auszuführen brauche, um eine Loggingausgabe zu machen. Es wäre sehr unpraktisch, wenn ich für jede Loggingausgabe fünf Zeilen mit immer demselben Code pro Ausgabe einfügen müsste. Außerdem kann sich die Funktion auch noch um andere Dinge kümmern, die vielleicht definiert sein müssen, bevor die Ausgabe getätigt werden kann. Das ist für das benutzende Coding transparent.

    asc schrieb:

    Aber das ist nur meine Meinung: tue einfach was du meinst. Wenn du jedesmal aufs neue die Datei öffnest hast du jedenfalls ganz ähnliche Probleme (1. ist dies langsam, 2. kann der Dateizugriff fehlschlagen...). Ich bezweifel das die Loggingbibliotheken von Java jedesmal neue Dateien öffnen.

    Ein Performanceproblem habe ich hier definitiv nicht, da ich nur an sehr hochleveligen Stellen Ausgaben generiere. Daher ist die Zeit fast egal. Es ist mir in erster Linie wichtig, dass die Aufrufe einfach sind und dass definitv alles in der Datei ankommt.

    Dass der Dateizugriff fehlschlagen kann, ist zu vernachlässigen. Wenn das der Fall ist, schlägt auch so einiges anderes fehl und das ganze System wird nicht laufen.

    Ob eine Loggingbibliothek jedes Mal eine Datei öffnet oder nicht, hängt sicherlich davon ab, für welchen Zweck sie eingesetzt wird. Wenn sie Massenlogs bewältigen können muss, und man davon ausgehen kann, dass dasLoggingsystem weiterläuft, auf wenn das Restcoding anschmiert, kann man ohne weiteres eine gepufferte Lösung verwenden, die auch die Datei nicht jedes Mal neu öffnet. In meinem Fall ist das wie gesagt nicht das ausschlaggebende Kriterium für die Performance und ich logge nicht viel. Der Hauptteil meines rFactor Plugnis läuft sowieso in Java und da habe ich deutlich bessere Kontrolle über alles.

    Marvin


Log in to reply