Malloc после перемещения указателя не работает в C? - PullRequest
0 голосов
/ 28 июня 2018

Я хочу загрузить словарь, используя TRIE. Первые три части кода работали как положено. Но я попытался сократить третью часть кода, тогда он не работал, не добавляя nodes к TRIE.

Вот часть объявления:

#define ALPHABET_SIZE 27

// define a node for a TRIE.
struct node
{
    _Bool end_of_word;
    struct node *next[ALPHABET_SIZE];
};

// create a TRIE
struct node *root = malloc(sizeof(struct node));

// create a mover.
struct node *mover = root;

// read dictionary file
FILE *dictptr = fopen(dictionary, "r");

Главное начинается отсюда:

//load dictionary word by word;
char c;
while ((c = fgetc(dictptr)) != EOF)
{
    if (c == '\n')
    {
        mover->end_of_word = 1;
        mover = root;
    }

Вот где я хочу оптимизировать:

    else
    {
        if (c == '\'')
        {
            mover->next[ALPHABET_SIZE - 1] = malloc(sizeof(struct node));
            mover = &mover->next[ALPHABET_SIZE - 1];
        }
        else
        {
            mover->next[c - 97] = malloc(sizeof(struct node));
            mover = &mover->next[c - 97];
        }


        // check if memory allocation is successful.
        if (mover == NULL)
        {
            unload();
            fprintf(stderr, "unable to allocate memory to new node.\n");
            return false;
        }
    }

А вот что я оптимизировал:

    else
    {
        if (c == '\'')
        {
            mover = &mover->next[ALPHABET_SIZE - 1];
        }
        else
        {
            mover = &mover->next[c - 97];
        }
        mover = malloc(sizeof(struct node));

1 Ответ

0 голосов
/ 08 января 2019

Делая то, что вы делали, вы «отделяли» цель назначения от значения lvalue получателя в mover->next[...], тем самым разрушая исходную функциональность кода. В вашей версии mover->next[...] остается без изменений.

Если бы кто-то буквально хотел устранить здесь дублирование кода, можно было бы сделать что-то следующим образом

    struct node **pmover;

    if (c == '\'')
      pmover = &mover->next[ALPHABET_SIZE - 1];
    else
      pmover = &mover->next[c - 97];

    mover = *pmover = malloc(sizeof(struct node));

Это будет буквальная реализация вашего намерения, которую также можно переписать как

    struct node **pmover = &mover->next[c == '\'' ? ALPHABET_SIZE - 1 : c - 97];
    mover = *pmover = malloc(sizeof(struct node));

Хотя лучшей идеей, на мой взгляд, будет

    struct node *new_node = malloc(sizeof(struct node));

    if (c == '\'')
      mover->next[ALPHABET_SIZE - 1] = new_node;
    else
      mover->next[c - 97] = new_node;

    mover = new_node;

(или эквивалентная версия ?:).

...