C строка добавить - PullRequest
       2

C строка добавить

0 голосов
/ 18 мая 2011

Я ищу эффективный способ добавления нескольких строк.
Он должен работать так: C ++ std :: string :: append или JAVA StringBuffer.append.

Я написал функцию, которая фактически перераспределяет предыдущий указатель источника и выполняет strcat.

Я считаю, что это неэффективный метод, так как компилятор может реализовать это бесплатно и malloc.

Другой способ, которым я мог бы придумать (например, std :: vector), - это выделить память навалом (например, 1 КБ) и выполнить strcpy. В этом случае каждый вызов добавления проверяет, превышает ли общее требуемое выделение (1200 байт) объем, выделенный в массе, и перераспределение до 2 КБ. Но в этом случае память будет потрачена впустую.

Я ищу баланс между вышесказанным, но предпочтение отдается производительности.

Какие другие подходы возможны. Пожалуйста, предложите.

Ответы [ 4 ]

4 голосов
/ 18 мая 2011

Я бы добавил каждую строку в список и добавил бы длину каждой новой строки к промежуточному итогу. Затем, когда вы закончите, выделите место для этой суммы, пройдитесь по списку и введите каждую строку в только что выделенное пространство.

2 голосов
/ 18 мая 2011

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

Начните с «разумного» буфера, поэтому вам не нужно делать realloc() s для размеров 1, 2, 4, 8, 16, которые будут поражены большим количеством ваших строк.

Начало в 1024 байта означает, что у вас будет один realloc(), если вы нажмете 2048, секунду, если вы нажмете 4096, и так далее. Если безудержное потребление памяти вас пугает, ограничьте скорость роста, когда она достигнет чего-то достаточно большого, например, 65536 байт или чего-то еще, это зависит от ваших данных и толерантности памяти.

Также убедитесь, что вы буферизуете текущую длину, чтобы вы могли выполнить strcpy() без необходимости сначала ходить по строке, чтобы найти длину.

0 голосов
/ 18 мая 2011

Я бы сделал что-то вроде этого:

typedef struct Stringbuffer {
    int capacity;     /* Maximum capacity. */
    int length;       /* Current length (excluding null terminator). */
    char* characters; /* Pointer to characters. */
} Stringbuffer;

BOOL StringBuffer_init(Stringbuffer* buffer) {
    buffer->capacity = 0;
    buffer->length = 0;
    buffer->characters = NULL;
}

void StringBuffer_del(Stringbuffer* buffer) {
    if (!buffer)
        return;

    free(buffer->characters);

    buffer->capacity = 0;
    buffer->length = 0;
    buffer->characters = NULL;
}

BOOL StringBuffer_add(Stringbuffer* buffer, char* string) {
    int len;
    int new_length;

    if (!buffer)
        return FALSE;

    len = string ? strlen(string) : 0;

    if (len == 0)
        return TRUE;

    new_length = buffer->length + len;

    if (new_length >= new_capacity) {
        int new_capacity;

        new_capacity = buffer->capacity;

        if (new_capacity == 0)
            new_capacity = 16;

        while (new_length >= new_capacity)
            new_capacity *= 2;

        new_characters = (char*)realloc(buffer->characters, new_capacity);
        if (!new_characters)
            return FALSE;

        buffer->capacity = new_capacity;
        buffer->characters = new_characters;
    }

    memmove(buffer->characters + buffer->length, string, len);
    buffer->length = new_length;
    buffer->characters[buffer->length] = '\0';

    return TRUE;
}
0 голосов
/ 18 мая 2011

Пример функции для объединения строк

void
addToBuffer(char **content, char *buf) {
    int textlen, oldtextlen;
    textlen =  strlen(buf);
    if (*content == NULL)
        oldtextlen = 0;
    else
        oldtextlen = strlen(*content);
    *content = (char *) realloc( (void *) *content, (sizeof(char)) * (oldtextlen+textlen+1));
    if ( oldtextlen != 0 ) {
        strncpy(*content + oldtextlen, buf, textlen + 1);
    } else {
        strncpy(*content, buf, textlen + 1);
    }
}

int main(void) {
    char *content = NULL;
    addToBuffer(&content, "test");
    addToBuffer(&content, "test1");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...