У меня есть эта система журналирования, для которой я ищу ярлык для некоторых манипуляций со строками.
Система журналирования используется через функциональные макросы, которые затем пересылаются на один вызов функции. Например, #define Warning (...) LogMessage (eWarning, __VA_ARGS __);
.
LogMessage затем выполняет snprintf
в новый буфер и затем представляет это сообщение любым объектам журнала случиться быть установленным; printf, OutputDebugString и т. д.
К сожалению, я столкнулся с проблемой, когда имеющийся у нас буфер недостаточно велик, поэтому выходные данные усекаются. Я также понял, что этот метод потерпит неудачу, если в выходном сообщении есть символы процента, как snprintf попытается обработать va_args. Наконец, поскольку большинство наших сообщений журнала не используют va_args, кажется глупым копировать строку только для того, чтобы представить ее регистраторам.
Итак, учитывая мой прототип функции, я смогу перегружаться в зависимости от присутствия из эллипсов? Другими словами, могу ли я предположить, что я могу сделать что-то вроде:
LogMessage(LogLevel, const char* message, ...);
LogMessage(LogLevel, const char* message);
Мои попытки Google не дали ничего особенно полезного (просто показывает мне, что эллипсы будут совпадать, если ничего не происходит, в отличие от моих требований, которые ничего не соответствует), и мой первоначальный удар при реализации просто дал мне неоднозначную ошибку вызова функции.
С ошибкой я должен просто принять, что не могу этого сделать, но мне интересно, если это просто компилятор, который я использую, или, может быть, я делаю это неправильно. Я могу добиться аналогичного эффекта с
// edited version of what I really have to remove our local APIs,
// please excuse minor errors
const char* message = NULL;
char buffer[512];
va_list args;
va_start(args, format);
if(strcmp(format, "%s") == 0) {
message = va_arg(args, const char*);
}
else if (strchr(format, '%') == NULL) {
message = format;
}
else {
vsnprintf(buffer, 512, format, args);
message = buffer;
}
va_end(args);
... но это кажется расточительным в типичном случае, который можно узнать просто по количеству передаваемых параметров. Например, если эллипсы ничего не соответствуют, выберите другую функцию? Если это не работает, есть ли другой способ, который я могу попробовать, который не требует, чтобы пользователь определился с именем макроса, какая функция будет вызвана? Честно говоря, это не так уж и много об «растрате», когда я понял, что если кто-то случайно сказал Ошибка («Буфер не заполнен на 100%»);
в своем сообщении журнала и получил «Буфер не 1007.732873e10ull» как результат.
Редактировать: Хотя мой пример получил ответ «не делай этого», можно ли ответить на сам вопрос?
Я также понял, что этот метод не сработает, если в выходном сообщении есть символы процента, так как snprintf попытается обработать va_args.
Тогда будьте осторожны. Если задокументировано, что ваша функция принимает строки формата в стиле printf, то ответственность за экранирование любых знаков процента лежит на вызывающем объекте. На самом деле это не ваша работа - пытаться обрабатывать недопустимые строки формата.
Честно говоря, дело даже не в «отходах», как только я понял, что если кто-то случайно сказал
Error("Буфер не заполнен на 100%");
в своем сообщении журнала и получил "Буфер не 1007.732873e10ull " как результат.
Я думаю, вам лучше придерживаться идеала C++.В методах Java обычно проверяются допустимые аргументы и выдаются исключения при передаче недопустимых значений. В C++ вы просто позволяете вызывающим абонентам выстрелить себе в ногу. Лучше, чтобы они написали 100%%
, чем прыгать через обручи, чтобы защитить их от изучения того, как правильно вызывать вашу функцию.