Добавление поддержки форматирования в реализацию пользовательской строки - C - PullRequest
1 голос
/ 09 октября 2010

У меня есть приложение C (не использующее функции C99), которое выполняет тяжелую обработку строк.Поскольку длины строк неизвестны, статически распределенные буферы для меня не вариант.Я создал простую string реализацию, которая абстрагирует нулевое завершение и динамическое расширение буферов.

Вот как это выглядит,

struct strbuf {
    char *buffer;            /* null terminated buffer */
    size_t length;           /* length of the string excluding null terminator */
    size_t allocated;        /* total memory allocated */
};

add функция, которая добавляетпредоставленная строка в буфер.

int strbuf_add(struct strbuf *string, const char *c)
{
    if(string == NULL) return 0;

    while(*c != '\0') {
        if(!add_char(string, *c++))
            return 0;        
    }

    return 1;
}

static int add_char(struct strbuf *string, char c)
{
    size_t space_available;

    assert(string != NULL);

    space_available = string->allocated - string->length;
    if(space_available <= 1) {
        if(!grow_buffer(string)) {
            return 0;
        }
    }
    string->buffer[string->length++] = c;
    string->buffer[string->length] = '\0';

    return 1;
}

Теперь мне нужно добавить новый метод, например, addformatted, который будет иметь формат, подобный sprintf.Мне интересно, что было бы лучшим способом сделать это?Ниже приведены мои мысли.

  1. Использование vsnprintf.Но я не уверен, что это портативно и имеет одинаковое поведение на всех платформах.
  2. Напишите синтаксический анализатор формата самостоятельно.Но это, кажется, больше работы.

Будет полезна любая помощь в реализации этого.Меня интересуют только портативные решения.

  • Dev Env: Linux с GCC
  • Ожидается компиляция на MSVC

Ответы [ 2 ]

1 голос
/ 10 октября 2010

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

0 голосов
/ 09 октября 2010

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

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

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