написание / выделение списка строк в C

Я делаю список строк в C, и я не мог найти ничего онлайн, чтобы легко добавить, а затем очистить список строк. Это было бы близко к функции «push» Perl.

Я хотел бы поделиться кодом, который я придумал здесь:

#include <stdio.h>//printf
#include <stdlib.h>//EXIT_FAILURE, malloc, realloc
#include <string.h>//need for strcmp and strlen

void *add_name(char **restrict array, size_t *restrict size, size_t *restrict number_of_names, const char *restrict NAME) {//this function works, when freed inside main()
    for (unsigned int name = *number_of_names-1; name <= 0; name--) {
        if (strcmp(array[name], NAME) == 0) {
            return array;//if this name is already in the list, don't add it
        }
    }
    const size_t NAME_SIZE = strlen(NAME)*sizeof(char)+sizeof(char*);
    *size += NAME_SIZE;
    array = realloc(array, *size);
    if (array == NULL) {
        puts("realloc of array failed.n");
        exit(EXIT_FAILURE);
    }
    array[*number_of_names] = malloc(NAME_SIZE);
    if (array[*number_of_names] == NULL) {
        printf("alloc of array[%zu] failed.n", *number_of_names);
        exit(EXIT_FAILURE);
    }
    strcpy(array[*number_of_names], NAME);
    *number_of_names += 1;
    return array;
}

void *clear_names(char **restrict array, size_t *restrict size, size_t *restrict number_of_names) {//empty the list of names
    for (size_t name = 0; name < *number_of_names; name++) {
        free(array[name]); array[name] = NULL;//this is missing something
        if (array[name] != NULL) {
            printf("free of array[%zu] failed.n", name);
        }
    }
    *number_of_names = 0;
    *size = sizeof(char);
    array = realloc(array, *size);
    if (array == NULL) {
        printf("realloc of array failed @ line %un",__LINE__);
        exit(EXIT_FAILURE);
    }
    return array;
}

int main (void) {
    puts("This program demonstrates how to add to and clear a list of names.");
    size_t name_list_size = sizeof(char);
    char **name_list = malloc(name_list_size);
    size_t number_of_names = 0;
    name_list = add_name(name_list, &name_list_size, &number_of_names, "James");
    name_list = add_name(name_list, &name_list_size, &number_of_names, "Mary");
    name_list = add_name(name_list, &name_list_size, &number_of_names, "Mary");
    name_list = add_name(name_list, &name_list_size, &number_of_names, "Thomas");
    for (size_t name = 0; name < number_of_names; name++) {
        printf("%sn",name_list[name]);
    }
    name_list = clear_names(name_list, &name_list_size, &number_of_names);
//
    name_list = add_name(name_list, &name_list_size, &number_of_names, "Matthew");
    name_list = add_name(name_list, &name_list_size, &number_of_names, "Mark");
    name_list = add_name(name_list, &name_list_size, &number_of_names, "Luke");
    name_list = add_name(name_list, &name_list_size, &number_of_names, "John");
    for (size_t name = 0; name < number_of_names; name++) {
        printf("%sn",name_list[name]);
    }
//
    name_list = clear_names(name_list, &name_list_size, &number_of_names);
    name_list = add_name(name_list, &name_list_size, &number_of_names, "Titus");
    printf("size = %zu  number_of_names = %zun", name_list_size, number_of_names);
    name_list = add_name(name_list, &name_list_size, &number_of_names, "Peter");
    printf("size = %zu  number_of_names = %zun", name_list_size, number_of_names);
    name_list = add_name(name_list, &name_list_size, &number_of_names, "Bartholomew");
    printf("size = %zu  number_of_names = %zun", name_list_size, number_of_names);
    name_list = add_name(name_list, &name_list_size, &number_of_names, "Paul");
    printf("size = %zu  number_of_names = %zun", name_list_size, number_of_names);
    for (size_t name = 0; name < number_of_names; name++) {
        printf("%sn",name_list[name]);
    }
    name_list = clear_names(name_list, &name_list_size, &number_of_names);
    free(name_list); name_list = NULL;
    return 0;
}

1 ответ

  1. Я бы предложил следующие предложения:

    • назначьте reallocвременному указателю, поэтому если он возвращает NULL, вы не уничтожаете array
    • использовать strdupвместо mallocдля хранения строк
    • используется lsearchдля проверки и вставки строки
    • при увеличении размераarray, делайте это удвоением вместо линейного
    • упакуйте массив, его количество и емкость в a struct(см. ниже) и передайте это в качестве аргумента функциям add & clear

    Вам нужно добавить функцию сравнения для передачи lsearch. Если lsearchимя добавляется, оно обновляет счетчик. Распределение по-прежнему зависит от вас, поэтому перед вызовом убедитесь, что емкость превышает количество.

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

    Одним из преимуществ использования структуры является возможность использования более коротких имен, например:

    struct name_list_t { 
           char **array; 
           size_t n, capacity; } names = { .array = NULL };
    

    // эта функция работает, когда освобождается внутри main()

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

    HTH.