2016-12-04 9 views
3

У меня есть процесс MPI, который мне нужно распечатать в файл. В системе MPI используются функциональные команды, такие как MPI_File_iwrite, которые принимают буфер (например, указатель символа) и целую длину. Затем буфер печатается в файл.Учитывая инструкцию printf в C, как мне построить буфер char * и узнать его длину?

Итак, чтобы распечатать то, что мне нужно для печати в файл, мне нужно как-то заменить функцию printf функцией, которая преобразует преобразование форматирования в буфер char *. Это проблематично, так как строки могут изменяться по длине ... например:

printf("something %d, %d, %d, %f, etc.",x,y,z,p,d,...); 

Как восстановить строку, которая производит Printf форматирование, выяснить, что длина, и передать его как символ * к функция mpi?

+0

1) 'printf' - это функция, а не инструкция. 2) 'printf' не генерирует строку (соответственно' char [] '. 3)' char * '- это указатель на' char', а не массив. – Olaf

+0

Если 'printf()' делает что-то вроде 'printf ("% c ", 0);', а затем пытается использовать 's (n) printf (some_buffer, ...); len = strlen (some_buffer); 'не будет определять правильное количество напечатанных символов. Лучше всего использовать возвращаемое значение 'snprintf()'. – chux

ответ

7

Похоже, вы хотите использовать snprintf для достаточно большого буфера.

Если буфер был достаточно большим, возвращаемое значение snprintf равно количеству напечатанных символов. Вы можете вычислить длину выходной строки как минимум размера буфера и возвращаемого значения snprintf.

+1

Получил, спасибо (все еще только пару месяцев на C) – bordeo

+1

Пожалуйста, отметьте вопрос как можно скорее. –

+0

Вам не нужно использовать 'strlen()'; 'snprintf()' сообщает вам, сколько символов должно было быть отправлено. Если количество символов, которые вы указали, слишком мало, выход будет усечен. –

3

Основываясь на ваш вопрос, я думаю, что ответ заключается в использовании sprintf() или snprintf(), а не printf() - sprintf() выходов в буфер и возвращает количество записанных символов без какой-либо проверки, что переданная буфер достаточно велика. snprintf() принимает дополнительный аргумент, определяющий максимальное количество байтов для записи (что является более безопасным подходом).

char my_buf[MAX_LENGTH]; 
int bytes_written; 

// using snprintf 
bytes_written = snprintf(my_buf, MAX_LENGTH, "%d %d ...", arg0, arg1 ...); 

Обратите внимание, что sprintf() и варианты также требуется дополнительные байты для терминатора символа \0 таким образом это должно быть отражено в вашем определенном размере буфера. Возвращаемое значение (количество записанных байтов) не включает символ терминатора.

+2

В целом, лучше всего забыть о существовании 'sprintf()' и его родственников; вы должны использовать только 'snprintf()', потому что они защищают вас от переполнения буфера. Тем не менее, если у вас есть уверенность в том, что ваш буфер достаточно велик, а выходные данные достаточно малы, 'sprintf()' все еще можно использовать, но было бы предпочтительнее подчеркнуть 'snprintf()' first и упомянуть 'sprintf()' в одноразовом комментарии. –

5

Вы можете «напечатать» 0 байтов указателю NULL с snprintf(). В этом случае ни одна строка не будет записана, но snprintf() по-прежнему будет вести себя нормально относительно ее возвращаемого значения. Затем вы можете выделить достаточно большой буфер.

Например:

size_t len; 
len = snprintf(NULL, 0, "something %d, %d, %d, %f, etc.",x,y,z,p,d,...); 
char *buf = malloc(len + 1); 
snprintf(buf, len + 1, "something %d, %d, %d, %f, etc.",x,y,z,p,d,...); 

Это справедливо только в C99 и далее.

+1

Пользователь этого кода должен помнить, что вы вызываете 'free()' on 'buf' после того, как' 'buf' больше не требуется для предотвращения утечек памяти. – theorifice

+0

Примечание: 'snprintf()' возвращает 'int'. Отрицательное возвращаемое значение указывает на ошибку. – chux

+0

A * мощность * погрешность. Есть ли обнаруженная ошибка вывода, с которой может справиться 'snprintf()'? – giusti