Учитывая оператор printf в C, как мне создать буфер char * и узнать его длину?

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

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

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

Как мне восстановить строку, которую производит printf-форматирование, выяснить, какая длина, и передать ее как char * в функцию mpi?

3 ответа

Решение

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

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

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

Например:

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

Это действительно только в C99 и далее.

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

Исходя из вашего вопроса, я думаю, что ответ заключается в использовании 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 так что это должно быть отражено в заданном вами размере буфера. Возвращаемое значение (количество записанных байтов) не включает символ-терминатор.

Другие вопросы по тегам