webentwicklung-frage-antwort-db.com.de

Übergabe variabler Argumente an eine andere Funktion, die eine Liste variabler Argumente akzeptiert

Ich habe also 2 Funktionen, die beide ähnliche Argumente haben

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

Jetzt ruft exampleexampleB auf, aber wie kann ich die Variablen in der Variablenargumentliste weitergeben, ohne exampleB zu ändern (da dies auch bereits an anderer Stelle verwendet wird).

92
Not Available

Sie können es nicht direkt tun; 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...
}
107

Vielleicht werfen Sie hier einen Stein in einen Teich, aber mit C++ 11-Vorlagen scheint das ganz in Ordnung zu sein:

#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++.

23

sie sollten Versionen dieser Funktionen erstellen, die eine va_list verwenden und diese übergeben. Schauen Sie sich vprintf als Beispiel an:

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

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

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

Ich war überhaupt nicht an der Leistung interessiert (ich bin sicher, dass dieser Teil des Codes auf verschiedene Weise verbessert werden kann, zögern Sie nicht, dies zu tun :)).

//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 nutzen

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 mancher Hinsicht schön, aber praktisch werden sie schrecklich, wenn Sie so etwas mit kleinen Zeichenfolgen wie Klammern, Doppelpunkten und Kommas zwischen den Zahlen drucken möchten.

4
Axel

Übrigens haben viele C-Implementierungen eine interne v? Printf-Variante, die IMHO Teil des C-Standards hätte sein sollen. Die genauen Details variieren, aber eine typische Implementierung akzeptiert eine Struktur, die einen Zeiger für die Zeichenausgabe und Informationen darüber enthält, was passieren soll. Dadurch können printf, sprintf und fprintf alle den gleichen "Kern" -Mechanismus verwenden. Vsprintf könnte beispielsweise so aussehen:

 ungültig s_out (PRINTF_INFO * p_inf, char ch) 
 {
 (* (p_inf-> destptr) ++) = ch; 
 p_inf-> result ++; 
} 
 
 int vsprintf (char * dest, const char * fmt, va_list args) 
 {
 PRINTF_INFO p_inf; 
 p_inf.destptr = dest; 
 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 eine Implementierung die Funktion core_printf (und den von ihr verwendeten Setup-Mechanismus) verfügbar macht, kann sie mit allen möglichen Variationen erweitert werden.

2
supercat

Ein möglicher Weg ist die Verwendung von #define:

#define exampleB(int b, ...)  example(0, b, __VA_ARGS__)
0
Shai

Basierend auf dem Kommentar, dass Sie vsprintf umbrechen und dies als C++ markiert ist, würde ich vorschlagen, dies nicht zu versuchen, sondern Ihre Schnittstelle so zu ändern, dass stattdessen C++ iostreams verwendet wird. Sie bieten Vorteile gegenüber der print - Reihe von Funktionen, z. B. Typensicherheit und die Möglichkeit, Elemente zu drucken, die printf nicht verarbeiten kann. Einige Überarbeitungen könnten in Zukunft erhebliche Schmerzen ersparen.

0
Mark B