【问题标题】:Infinite Loop when using 'for' with pointer as loop variable使用带有指针作为循环变量的'for'时的无限循环
【发布时间】:2018-10-13 17:36:43
【问题描述】:

我对编码很陌生,遇到了一个问题。我试图自己解决它并且一直在谷歌搜索,但我仍然没有解决这个问题。也许你们中的一个可以提供帮助?

这是我的代码:

int main(int argc, char **argv) {
    struct node {
        char *str;
        int count;
        struct node *next;
    };

    struct node head = { argv[1], 1, NULL };
    for (int i = 2; i < (argc); i++) {
        for (struct node *p = &head; (p != NULL); p = p->next) {
            printf("%s,%s\n", argv[i], p->str);
            if (strcmp(argv[i], p->str) == 0) {
                printf("case1\n");
                p->count++;
                break;
            }
            else if ((strcmp(argv[i], p->str) != 0) && p->next) {
                printf("case2\n");
                printf("Adresse, auf die p zeigt: %p", &p);
                continue;
            }
            else if ((strcmp(argv[i], p->str) != 0) && (!p->next)) {
                printf("case3\n");
                struct node *oldhead = &head;
                head.str = argv[i];
                head.count = 1;
                head.next = oldhead;
                break;
            }

        }
    }

    // Print how many times each string appears

    return 0;
}

目标是创建一个链接列表,其中包含我在调用程序时提供给main() 的所有参数。如果有重复,结构应该计算它们。例如,如果我调用像./a.out foo fool foo 这样的程序,结果应该是一个长度为2 的列表,其中第一个元素包含字符串"foo" 和计数2,第二个元素包含字符串"fool" 并且有1 的计数。问题是内部 for 循环中的 else if-statement。这是实际应该使用内部 for 循环并将p-&gt;next 分配给p 的唯一部分。不幸的是,这并没有发生。结果是内部 for 循环一遍又一遍地开始,并且指针 p 一直指向同一个地址(我使用 printf 来解决这个问题)。

你们中有人知道这可能是什么问题吗?我尽我所能,并试图在网上找到解决方案......

非常感谢!!!

【问题讨论】:

  • 你在哪里分配你的其他节点?
  • 。 o O(为什么每个第二个提问者都说“这是我的全部代码”,但不包括#includes??它是一个 PITA!)
  • 为什么要使用效率最低的数据结构之一?既然有std::list&lt;&gt;,为什么要自己实现呢?
  • @Swordfish 因为C中没有std::list&lt;&gt;
  • @WhozCraig 我发誓,我看到了 C++ 标签。好吧,第一个问题仍然存在。

标签: c pointers for-loop infinite-loop


【解决方案1】:

问题出在这部分代码

   else if ((strcmp(argv[i], p->str) != 0) && (!p->next)) {
        printf("case3\n");
        struct node *oldhead = &head;
        head.str = argv[i];
        head.count = 1;
        head.next = oldhead;
        break;
    }

你需要分配一个新的结构体,然后把它的地址放在最后一个结构体条目中。

       else if ((strcmp(argv[i], p->str) != 0) && (!p->next)) {
            printf("case3\n");
            struct node *oldhead = p;
            p = (struct node *) malloc(sizeof(node));
            if (p == NULL) { .... manage the error ... }
            oldhead->next = p;
            p->str = argv[i];
            p->count = 1;
            p->next = NULL;
            break;
        }

现在您正在创建节点并将它们串在一起。您之前有效地更新了相同的node

【讨论】:

  • 非常感谢您的帮助。现在真的明白了。
【解决方案2】:
        struct node *oldhead = &head;
        head.str = argv[i];
        head.count = 1;
        head.next = oldhead;

这不是创建一个新节点。它只是创建对同一节点的新引用,因此当您尝试读取链表直到结束时会导致无限循环。因此,您的程序只有一个节点。您需要实际分配并创建新的。

【讨论】:

  • 感谢您的快速回复!也就是说,问题实际上不是第二种情况,而是第三种情况?
  • @user10500064 如果此答案解决了您的问题,您可以通过单击其复选标记将其标记为已接受吗?
  • 正如@JosephSible 所指出的,支持有帮助的答案,选择最能回答您的问题的答案。这会帮助那些帮助你的人。
【解决方案3】:

这里的主要问题是

struct node *oldhead = &head;

你应该做什么malloc:

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

所以你真的为你的新节点分配了一块内存。因为你有malloc,所以你也应该在程序的最后加上free

while(...) {
   free(deepest_node)
}

您执行上述循环的方式是从链表中最远的节点一直回到head

另一个问题是,您不应该将新节点附加到head

head.next = oldhead;

但应该是p,这是您的链表中的最后一个节点:

p -> next = oldhead;

【讨论】:

  • 非常感谢!我不明白这部分代码是问题所在。所以感谢您的帮助!!
  • 顺便说一句,取决于您使用的编译器,标准 C 代码不应在代码中间定义变量,而应仅在开头定义变量。例如循环中的struct node *p 不是一个好习惯,否则可能会引发编译器抱怨(但在 C++ 中完全没问题)
  • 感谢您的建议!从现在开始,我只会在开头定义变量。
  • 我应该在主函数的末尾还是在代码的最后使用“free”?我正在考虑使用这个循环: for (struct node *f = &head; f; f = f->next) { free(f); }
  • 不,不要。你释放f,然后尝试阅读f-&gt;next,这很糟糕。关于你应该在哪里释放的问题,我希望你不再需要内存。在您的情况下,主要功能的结尾和代码的结尾应该是同一件事。
猜你喜欢
  • 2013-06-26
  • 1970-01-01
  • 1970-01-01
  • 2019-09-27
  • 1970-01-01
  • 2017-09-21
  • 2011-12-23
  • 2018-01-27
  • 2021-03-23
相关资源
最近更新 更多