Mam klasę, która zawiera funkcję „błędu”, która sformatuje jakiś tekst. Chcę zaakceptować zmienną liczbę argumentów, a następnie sformatować je za pomocą printf.
Przykład:
class MyClass
{
public:
void Error(const char* format, ...);
};
Metoda Error powinna przyjąć parametry, wywołać printf / sprintf w celu sformatowania go, a następnie coś z tym zrobić. Nie chcę sam pisać całego formatowania, więc warto spróbować dowiedzieć się, jak użyć istniejącego formatowania.
źródło
sizeof(buffer)
zamiast 256.Powinienem był przeczytać więcej na temat istniejących pytań w przepełnieniu stosu.
C ++ Przekazywanie zmiennej liczby argumentów to podobne pytanie. Mike F ma następujące wyjaśnienie:
To jest dokładnie to, czego szukałem. Wykonałem taką implementację testową:
void Error(const char* format, ...) { char dest[1024 * 16]; va_list argptr; va_start(argptr, format); vsprintf(dest, format, argptr); va_end(argptr); printf(dest); }
źródło
Szukasz funkcji wariadycznych . printf () i sprintf () są funkcjami wariadycznymi - mogą przyjmować zmienną liczbę argumentów.
Zasadniczo obejmuje to następujące kroki:
Pierwszy parametr musi wskazywać liczbę kolejnych parametrów. Więc w printf () parametr "format" daje takie wskazanie - jeśli masz 5 specyfikatorów formatu, to będzie szukał 5 więcej argumentów (w sumie 6 argumentów). Pierwszy argument może być liczbą całkowitą (np. "Moja funkcja (3, a, b, c) "gdzie" 3 "oznacza" 3 argumenty)
Następnie przejrzyj i pobierz każdy kolejny argument, używając funkcji va_start () itp.
Istnieje wiele samouczków, jak to zrobić - powodzenia!
źródło
Używanie funkcji z elipsami nie jest zbyt bezpieczne. Jeśli wydajność nie jest krytyczna dla funkcji dziennika, rozważ użycie przeciążenia operatora, tak jak w boost :: format. Możesz napisać coś takiego:
#include <sstream> #include <boost/format.hpp> #include <iostream> using namespace std; class formatted_log_t { public: formatted_log_t(const char* msg ) : fmt(msg) {} ~formatted_log_t() { cout << fmt << endl; } template <typename T> formatted_log_t& operator %(T value) { fmt % value; return *this; } protected: boost::format fmt; }; formatted_log_t log(const char* msg) { return formatted_log_t( msg ); } // use int main () { log("hello %s in %d-th time") % "world" % 10000000; return 0; }
Poniższy przykład ilustruje możliwe błędy z wielokropkami:
int x = SOME_VALUE; double y = SOME_MORE_VALUE; printf( "some var = %f, other one %f", y, x ); // no errors at compile time, but error at runtime. compiler do not know types you wanted log( "some var = %f, other one %f" ) % y % x; // no errors. %f only for compatibility. you could write %1% instead.
źródło
Prosty przykład poniżej. Zauważ, że powinieneś przekazać większy bufor i sprawdzić, czy bufor był wystarczająco duży, czy nie
void Log(LPCWSTR pFormat, ...) { va_list pArg; va_start(pArg, pFormat); char buf[1000]; int len = _vsntprintf(buf, 1000, pFormat, pArg); va_end(pArg); //do something with buf }
źródło
Spójrz na przykład http://www.cplusplus.com/reference/clibrary/cstdarg/va_arg/ , przekazują one liczbę argumentów do metody, ale możesz to ominąć i odpowiednio zmodyfikować kod (patrz przykład).
źródło