Jak przekazać zmienną liczbę argumentów do printf/sprintf
Mam klasę, która posiada funkcję" error", 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 błędów powinna przyjąć parametry, wywołać printf / sprintf, aby sformatować je, a następnie coś z nimi zrobić. Nie chcę sam pisać całego formatowania, więc warto spróbować i dowiedzieć się, jak korzystać z istniejącego formatowania.
7 answers
Bad
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);
}
Ten kod nie jest taki dobry. Używa bufora znaków o stałej wielkości, co może prowadzić do błędu przekroczenia bufora, jeśli łańcuch znaków jest patologicznie długi. Dowolny rozmiar {[2] } powinien wywołać flagę w twojej głowie. Ponadto, wywołanie printf
może napotkać problemy, Jeśli dest
zakończy się zawierając kody formatujące. Lepiej byłoby printf("%s", dest)
. Ale jeszcze lepiej byłoby użyć vprintf
lub vfprintf
:
Dobry
void Error(const char* format, ...)
{
va_list argptr;
va_start(argptr, format);
vfprintf(stderr, format, argptr);
va_end(argptr);
}
Jeśli chcesz manipulować ciągiem zanim go wyświetlisz i naprawdę potrzebujesz go najpierw przechowywać w buforze, proszę, użyj vsnprintf
zamiast vsprintf
. vsnprintf
zapobiegnie przypadkowemu przepełnieniu bufora.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-28 17:41:24
Spójrz na vsnprintf jak to zrobi co chcesz http://www.cplusplus.com/reference/clibrary/cstdio/vsprintf/
Będziesz musiał najpierw uruchomić ARG array va_list, a następnie ją wywołać.
Przykład z tego linku: / * przykład vsprintf * /
#include <stdio.h>
#include <stdarg.h>
void Error (char * format, ...)
{
char buffer[256];
va_list args;
va_start (args, format);
vsnprintf (buffer, 255, format, args);
//do something with the error
va_end (args);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-29 04:36:33
Używanie funkcji z elipsami nie jest zbyt bezpieczne. Jeśli wydajność nie jest krytyczna dla funkcji log, rozważ użycie przeciążenia operatora jak w formacie boost::. Mógłbyś 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ższa próbka pokazuje możliwe błędy z elipsami:
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.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-29 07:44:57
Powinienem przeczytać więcej na temat istniejących pytań w stack overflow.
C++ przekazywanie zmiennej liczby argumentów jest podobnym pytaniem. Mike F ma następujące wyjaśnienie:
Właśnie tego szukałem. Wykonałem taką implementację testową:Nie ma możliwości wywołania (np) printf nie wiedząc ile argumentów przechodzisz do niego, chyba że chcesz aby dostać się do niegrzecznych i nie przenośnych sztuczki.
Powszechnie stosowanym rozwiązaniem jest zawsze podaj alternatywną formę funkcje vararg, czyli printf ma vprintf, który pobiera va_list z....... The ... wersje są tylko otacza wersje va_list.
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);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:37
Szukasz funkcji wariacyjnych . printf () i sprintf() są funkcjami zmiennymi - mogą przyjmować zmienną liczbę argumentów.
Wiąże się to zasadniczo z następującymi krokami:
-
Pierwszy parametr musi wskazywać liczbę następujących parametrów. Tak więc w printf () parametr "format" podaje to wskazanie - jeśli masz 5 specyfikatorów formatu, to będzie szukał jeszcze 5 argumentów (w sumie 6 argumentów.) Pierwszy argument może być liczbą całkowitą(np. "mojfunction (3, a, b, c)" gdzie "3" oznacza "3 argumenty)
Następnie wykonaj pętlę i pobieraj każdy kolejny argument, używając va_start () itd. funkcje.
Jest mnóstwo tutoriali jak to zrobić-powodzenia!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-29 03:17:13
Prosty przykład poniżej. Uwaga powinieneś przejść do większego bufora i przetestować, 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
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-29 03:17:12
Spójrz na przykład http://www.cplusplus.com/reference/clibrary/cstdarg/va_arg / , przekazują liczbę argumentów do metody, ale można to ommit i odpowiednio zmodyfikować kod(patrz przykład).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-29 03:16:28