LINUX.ORG.RU

Variadic function странно ведет себя с double

 


0

1

День добрый! У меня была такая функция для форматированного вывода в строку:

std::string strprintf(const char* format, ...)
{
va_list argptr;
std::vector<char> buffer;

	va_start(argptr, format);

	std::size_t length = vsnprintf(NULL, 0, format, argptr)+1;
	buffer.resize(length, 0);

	vsnprintf(&buffer[0], buffer.size(), format, argptr);
	va_end(argptr);

return std::string(buffer.begin(), buffer.end() );
}
Все работало до тех пор пока не попробовал вывести переменную с плавающей точкой:
double pi = 3.14;
std::string pi_f = strprintf("f:pi=%f\n", pi);
Ны выходе получается нули, совсем не то, что ожидалось. Народ говорит что проблема связана с тем, что при передачи в "..." float преобразуется к double. Я сделал другую функцию:
template <typename... Args>
std::string strprintf(const char* format, Args&&... args)
{
std::vector<char> buffer;

	std::size_t length = snprintf(NULL, 0, format, std::forward<Args>(args)...)+1;
	buffer.resize(length, 0);
	snprintf(&buffer[0], buffer.size(), format, std::forward<Args>(args)...);

return std::string(buffer.begin(), buffer.end() );
}
Она хорошо работает. Но хочется еще понять как исправить первый вариант, чтобы float и double корректно выводились.


Народ говорит что проблема связана с тем, что при передачи в "..." float преобразуется к double.

Народ что-то говорит правильно, но понимает это плохо. Проблема не в этом, так как snprintf не глуп и понимает, что там будет double, а он там будет и во втором случае.

Проблема в повторном использовании va_list, так делать нельзя, его надо копировать, чтобы можно было использовать дважды. Можно сказать, что он работает как forward iterator.

std::string strprintf(const char* format, ...)
{
va_list argptr;
va_list argptr2;
std::vector<char> buffer;

    va_start(argptr, format);
    va_copy(argptr2, argptr);

    std::size_t length = vsnprintf(NULL, 0, format, argptr)+1;
    va_end(argptr);
    buffer.resize(length, 0);

    vsnprintf(&buffer[0], buffer.size(), format, argptr2);
    va_end(argptr2);

return std::string(buffer.begin(), buffer.end() );
}
xaizek ★★★★★
()
Последнее исправление: xaizek (всего исправлений: 2)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.