2017-02-09 5 views
2

Я кодирую под Arduino, и я хотел бы разработать функцию форматирования серийной печати, поэтому я пытаюсь использовать sprintf неизвестного размера буфера. В принципе, мы можем не говорить о Arduino и его серийном выходе, и рассмотреть возможность написания текста в буфер, а затем распечатать его, используя printf. Я попытался это одно:Wrapper for printf

#include <stdio.h> 
#include <stdarg.h> 

void printf0(const char* format, ...) { 
    va_list args; 
    va_start(args, format); 
    vprintf(format, args); 
    va_end(args); 
} 

void printf1(const char* format,...) { 
    va_list args; 
    va_start(args, format); 
    char buf[vsnprintf(NULL, 0, format, args)]; 
    sprintf(buf, format, args); 
    printf(buf); 
    va_end(args); 
} 

int main() 
{ 
    printf0("Hello, %d!\n", 15); 
    printf1("Hello, %d!\n", 15); 
    return 0; 
} 

printf0 функция является точным примером я нашел here. Мои попытки - это функция printf1, которая производит непредсказуемое число. Пример вывода вышеуказанной программы:

Hello, 15! 
Hello, 860799736! 
+0

'Sprintf (BUF, формат, арг),' должен быть 'vsnprintf (ЬиЙ, SizeOf ЬиМ, формат, args); '. – mch

+1

@LPs, вызывающие 'vsnprintf' с указателем' 'NULL' и размером' 0', возвращают только число символов 'char', которое функция записывает в буфер. – mch

+1

@ Jarod42 - Уверен, что речь идет о C++ вообще. Кажется, это обычный спам «двойной тег». – StoryTeller

ответ

4

args является va_list, так что вы не можете назвать sprintf с ним. Вы должны использовать vsprintf или vsnprintf:

sprintf(buf, format, args); 

должен быть

vsnprintf(buf, sizeof buf, format, args); 

Также вы должны добавить 1 к размеру buf для 0-терминатор строки:

char buf[vsnprintf(NULL, 0, format, args) + 1]; 

Кажется, что первый звонок vsnprintf изменяет args, поэтому вам нужно добавить

va_end(args); 
va_start(args, format); 

между 2 вызовами: http://ideone.com/5YI4Or

кажется, что первый вызов vsnprintf изменения args, но вы не должны вызывать va_start дважды. Вы должны использовать вместо va_copy, поэтому добавьте

va_list args2; 
va_copy(args2, args); 

после инициализации args. Также не забудьте позвонить va_end(args2); тоже:

http://ideone.com/loTRNL

Ссылка на страницу va_copy людей: https://linux.die.net/man/3/va_copy

+1

Это не работает на моей платформе: я подозреваю, что args модифицируется 'vsnprintf', поэтому вторая' vsnprintf' терпит неудачу. – LPs

+0

yup, хорошая точка для вашего замечания, как для добавления одного к размеру буфера. ваше решение будет проверено. – pt12lol

+0

фрагмент, предоставленный в конце вашего ответа. это именно то, что я хотел. Спасибо за ваше объяснение. – pt12lol