Заполнение статического строкового буфера в C через snprintf - PullRequest
0 голосов
/ 25 февраля 2011

У меня есть некоторый буфер и известный размер

#define BUFFER_SIZE 1024*1024
char buffer[BUFFER_SIZE];

Я должен заполнить этот буфер какой-нибудь сложной строкой.

int populate_string(char *buffer) {
    char *tbuffer = buffer;
    size_t tsize = BUFFER_SIZE;
    int rv;

    rv = snprintf(tbuffer, tsize, "foobar %s %d %s %D", ...);
    if (rv < 0) {
        printf("snprintf() error");
        return -1;
    } else if (rv >= tsize) {
        printf("overflow, increase buffer size");
        return -1;
    } else {
        tsize -= rv;
        tbuffer += rv;
    }

    // repeat snprintf's until string is fully populated

    return 0;
}

Итак, у меня есть три вопроса:

  1. Это лучший способ для динамического заполнения статической строки?
  2. Безопасен ли мой способ заполнения строки?
  3. Как я могу уменьшить количество строк? Эти проверки возвращаемого значения занимают много места, особенно если есть много snprintfs.

Ответы [ 3 ]

1 голос
/ 25 февраля 2011
  1. Зависит от того, что вы делаете с этими строками :) Очевидная альтернатива - использовать вместо этого связанные списки.
  2. Да, это безопасно.
  3. Иногда нет необходимости проверять, нет ли в snprintf ошибки или переполнения, поэтому вы можете использовать только одну проверку if ().
0 голосов
/ 25 февраля 2011

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

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

0 голосов
/ 25 февраля 2011

open_memstream и fmemopen могут вас заинтересовать:

http://linux.die.net/man/3/open_memstream

Вы можете заполнить свой буфер, открыв поток файлов в буфер, то есть:

FILE *f=fmemopen(buffer,BUFFER_SIZE,"w");
fwrite(f,...); 

Запись в этот поток приведет к ошибке (если вы отключите буферизацию), когда вы достигнете предела «буфера».

Также вы можете использовать open_memstream для создания потока в памяти, который автоматически изменяет размер додержи то, что пишешь в него.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...