Frage Übergeben von Variablenargumenten an eine andere Funktion, die eine Liste mit variablen Argumenten akzeptiert


Also habe ich 2 Funktionen, die beide ähnliche Argumente haben

void example(int a, int b, ...);
void exampleB(int b, ...);

Jetzt example Anrufe exampleB, aber wie kann ich die Variablen in der Variablenargumentliste ohne Änderung weitergeben exampleB (da dies auch schon woanders verwendet wird).


75
2017-08-20 12:22


Ursprung


Antworten:


Du kannst es nicht direkt machen; Sie müssen eine Funktion erstellen, die ein va_list:

#include <stdarg.h>

static void exampleV(int b, va_list args);

void example(int a, int b, ...)
{
    va_list args;
    va_start(args, b);
    exampleV(b, args);
    va_end(args);
}

void exampleB(int b, ...)
{
    va_list args;
    va_start(args, b);
    exampleV(b, args);
    va_end(args);
}

static void exampleV(int b, va_list args)
{
    ...whatever you planned to have exampleB do...
    ...except it calls neither va_start nor va_end...
}

89
2017-08-20 12:28



Sie sollten Versionen dieser Funktionen erstellen, die eine va_list enthalten, und diese übergeben. Ansehen vprintf als Beispiel:

int vprintf ( const char * format, va_list arg );

15
2017-08-20 12:26



Vielleicht hier einen Stein in einen Teich werfen, aber mit C ++ 11 variadic Vorlagen scheint es ziemlich gut zu funktionieren:

#include <stdio.h>

template<typename... Args> void test(const char * f, Args... args) {
  printf(f, args...);
}

int main()
{
  int a = 2;
  test("%s\n", "test");
  test("%s %d %d %p\n", "second test", 2, a, &a);
}

Zumindest funktioniert es mit g++.


9
2017-09-16 13:42



Übrigens haben viele C-Implementierungen eine interne v-Druckvariation, die IMHO Teil des C-Standards sein sollte. Die genauen Details variieren, aber eine typische Implementierung akzeptiert eine Struktur, die einen Zeichenausgabe-Funktionszeiger und Informationen enthält, die sagen, was passieren soll. Dadurch können printf, sprintf und fprintf alle denselben "Kern" -Mechanismus verwenden. Zum Beispiel könnte vsprintf etwas wie sein:

void s_out (PRINTF_INFO * p_inf, Zeichen ch)
{
  (* (p_inf-> destptr) ++) = ch;
  p_inf-> Ergebnis ++;
}

int vsprintf (char * dest, const char * fmt, va_list args)
{
  PRINTF_INFO p_inf;
  p_inf.destptr = Ziel;
  p_inf.result = 0;
  p_inf.func = s_out;
  core_printf (& p_inf, fmt, args);
}

Die Funktion core_printf ruft dann für jedes auszugebende Zeichen p_inf-> func auf; Die Ausgabefunktion kann dann die Zeichen an die Konsole, eine Datei, eine Zeichenfolge oder etwas anderes senden. Wenn die Implementierung die Funktion core_printf (und den von ihr verwendeten Setup-Mechanismus) verfügbar macht, kann man sie mit allen möglichen Variationen erweitern.


2
2017-08-20 14:34



Ich wollte auch printf einpacken und fand hier eine hilfreiche Antwort:

Wie übergeben Sie eine variable Anzahl von Argumenten an printf / sprintf

Ich war überhaupt nicht an der Leistung interessiert (ich bin mir sicher, dass dieser Teil des Codes in vielerlei Hinsicht verbessert werden kann, ich fühle mich dazu frei :)), dies ist nur für den allgemeinen Debug-Druck gedacht, also habe ich Folgendes getan:

//Helper function
std::string osprintf(const char *fmt, ...)
{
    va_list args;
    char buf[1000];
    va_start(args, fmt);
    vsnprintf(buf, sizeof(buf), fmt, args );
    va_end(args);
    return buf;
}

das kann ich dann so benutzen

Point2d p;

cout << osprintf("Point2d: (%3i, %3i)", p.x, p.y);
instead of for example:
cout << "Point2d: ( " << setw(3) << p.x << ", " << p.y << " )";

Die C ++ - Ostreams sind in einigen Aspekten schön, aber praktisch wird es entsetzlich, wenn Sie etwas wie dieses mit kleinen Strings wie Klammern, Doppelpunkten und Kommas zwischen den Zahlen drucken wollen.


2
2018-01-07 19:22



Basierend auf dem Kommentar, den Sie verpacken vsprintf, und dass dies als C ++ markiert ist, würde ich vorschlagen, dies nicht zu tun, aber ändern Sie Ihre Schnittstelle, um stattdessen C ++ iostreams zu verwenden. Sie haben Vorteile gegenüber der print Reihe von Funktionen, wie Typ Sicherheit und in der Lage, Elemente zu drucken, die printf wäre nicht in der Lage, damit umzugehen. Einige Nacharbeiten könnten in der Zukunft erhebliche Schmerzen ersparen.


0
2017-08-20 13:34



Wenn Sie den neuen C ++ 0x-Standard verwenden, können Sie dies möglicherweise mithilfe von Variadic-Vorlagen erledigen oder sogar diesen alten Code in die neue Vorlagensyntax konvertieren, ohne etwas zu brechen.


-1
2017-08-20 12:56