【问题标题】:Malloc after moving the pointer doesn't work in C?移动指针后的 Malloc 在 C 中不起作用?
【发布时间】:2018-12-06 21:36:50
【问题描述】:

我想使用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));

【问题讨论】:

  • 如果你有例如int a; if (some_condition) { a = 5; } else { a = 10; } a = 15; a 在该代码之后的值是多少?在您的“优化”代码的上下文中考虑这一点。
  • 谢谢。似乎通过将mover 分配给它的元素,我将该地址的副本从root 分配给mover,而不是直接更改root 中的地址。对吗?
  • 这似乎是正确的。
  • 我试着从链表的角度做一个图表。似乎在将其子元素值分配给它时,我使 mover 指向任何内容。这样,我打破了moverroot TRIE 之间的联系。这种理解正确吗?
  • 这是实际代码吗?您分配大小(结构注释)但结构实际上被命名为“节点”

标签: c pointers data-structures malloc trie


【解决方案1】:

通过执行您所做的操作,您将赋值目标与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;

(或基于?: 的等效版本)。

【讨论】:

  • 哦,我明白了。太精彩了。似乎我对pointer 的概念感到困惑,因此犯了这个简单的错误。非常感谢您帮助我度过难关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-25
相关资源
最近更新 更多