Использование массива строк для реализации таблицы символов в C - PullRequest
0 голосов
/ 05 апреля 2020

Я пытаюсь использовать массив структур для создания таблицы символов. Это то, что у меня есть до сих пор, но у меня возникают проблемы с выделением памяти в функции создания, верно ли то, что я до сих пор исправляю?

Я хочу что-то вроде этого как мой конечный результат для arr {{"sym1" ; 1}, {"sym2"; 2}, {"sym3"; 3}}

struct str_id {
  char* s;
  int id;
}

struct symbol_table {
  int count;
  struct str_id** arr;
}

struct symbol_table *symbol_table_create(void) {
  struct symbol_table *stt = malloc(sizeof(struct symbol_table));
  stt->count = 1;
  stt->arr =  malloc(sizeof(struct str_id*) * stt->count);
  return stt;

}

1 Ответ

1 голос
/ 05 апреля 2020
  • Используйте описательные имена для идентификаторов, а не crypti c короткие имена (например, s и str_id).
  • Избегайте системной венгерской нотации (то есть именования или Идентификаторы префиксов после их типа или «что они» означают «что они значат»).
    • В вашем случае, я предполагаю, что str_id является аббревиатурой для struct_id (или string_id) - что является плохим именем, потому что уже сразу очевидно, что это struct (или содержит строку ).
    • Он был популярен вплоть до 1990-х годов, когда программисты начали использовать более мощные редакторы и IDE, которые отслеживали типы переменных - сегодня это просто не нужно.
  • Всегда проверяйте, успешно ли выделена куча, сравнивая возвращаемые значения calloc и malloc с NULL. Это можно сделать с помощью if( some_pointer ) abort().
    • Не используйте assert( some_pointer ), поскольку утверждения включены только в отладочных сборках, вместо этого используйте abort, поскольку это означает ненормальное завершение программы по сравнению с exit.
  • Передайте параметр size_t, чтобы потребители могли указать размер таблицы символов.
  • Количество объектов, хранящихся в памяти, должно быть выражено как size_t (например, индексаторы массива). Никогда не используйте int для этого !
  • Вам нужно ставить точку с запятой в конце каждого struct определения.
  • Вы уверены, что хотите array-of-pointers-to-structs а не просто array-of-structs? В этом случае вы можете использовать встроенные структуры и использовать одно выделение для массива, вместо того, чтобы выделять каждый элемент отдельно.
  • Поскольку вы выполняете пользовательское выделение, вы также должны определить функцию деструктора.
struct symbol_table_entry {
  char* symbolText;
  int   id;
};

struct symbol_table {
  size_t count;
  struct symbol_table_entry** entries;
};

struct symbol_table* create_symbol_table( size_t count ) {
    struct symbol_table* stt = malloc( sizeof(struct symbol_table) );
    if( !stt )
    {
        abort();
    }
    stt->count = count;
    stt->entries = calloc( count, sizeof(struct symbol_table_entry) );
    if( !stt->entries ) {
        free( stt );
        abort();
    }
    // Note that calloc will zero-initialize all entries of the array (which prevents debuggers showing garbage string contents) so we don't need to do it ourselves.
    return stt;
}

void destroy_symbol_table( struct symbol_table* stt, bool free_strings ) {
    if( stt->entries ) {
        if( free_strings ) {
            for( size_t i = 0; i < stt->count; i++ ) {
                free( stt->entries[i]->symbolText );
            }
        }
        free( stt->entries );
    }
    free( stt );
}
...