У меня есть класс, содержащий функцию «ошибки», которая форматирует некоторый текст. Я хочу принять переменное количество аргументов, а затем отформатировать их с помощью printf.
Пример:
class MyClass
{
public:
void Error(const char* format, ...);
};
Метод Error должен принимать параметры, вызывать printf / sprintf для его форматирования, а затем что-то делать с ним. Я не хочу писать все форматирование самостоятельно, поэтому имеет смысл попытаться выяснить, как использовать существующее форматирование.
источник
sizeof(buffer)
вместо 256.Я должен был прочитать больше о существующих вопросах в переполнении стека.
С ++ Передача переменного числа аргументов - аналогичный вопрос. У Майка Ф. есть следующее объяснение:
Это именно то, что я искал. Я выполнил тестовую реализацию вот так:
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); }
источник
Вы ищете вариативные функции . printf () и sprintf () - это функции с переменным числом аргументов - они могут принимать переменное количество аргументов.
В основном это влечет за собой следующие шаги:
Первый параметр должен указывать на количество следующих параметров. Таким образом, в printf () параметр «format» дает это указание - если у вас есть 5 спецификаторов формата, тогда он будет искать еще 5 аргументов (всего 6 аргументов). Первый аргумент может быть целым числом (например, «myfunction (3, a, b, c) "где" 3 "означает" 3 аргумента)
Затем выполните цикл и получите каждый последующий аргумент, используя функции va_start () и т. Д.
Есть много руководств о том, как это сделать - удачи!
источник
Использование функций с эллипсами не очень безопасно. Если производительность не критична для функции журнала, рассмотрите возможность использования перегрузки оператора, как в boost :: format. Вы могли написать что-то вроде этого:
#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; }
В следующем примере показаны возможные ошибки с помощью эллипсов:
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.
источник
Простой пример ниже. Обратите внимание, что вы должны передать буфер большего размера и проверить, достаточно ли он большой или нет.
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 }
источник
Взгляните на пример http://www.cplusplus.com/reference/clibrary/cstdarg/va_arg/ , они передают количество аргументов методу, но вы можете опустить это и соответствующим образом изменить код (см. Пример).
источник