【问题标题】:C Linked List error not linking properlyC 链接列表错误未正确链接
【发布时间】:2018-04-24 07:49:10
【问题描述】:

我在网上找不到类似的问题,主要是因为我的问题更具体一些,并且可能是由某种逻辑错误引起的。

我正在尝试逐个阅读单词(已经完成)并制作一个链接列表(使用 typedef,已经完成)存储这些单词的所有实例及其频率。

发生的情况是我完成了代码的第一部分,即链表的初始化,但是,当它尝试链接更多节点时,程序很快就崩溃了。

当我使用输入运行代码时会发生以下情况:

C:\path-->test
hello
First word found: hello
head->word = hello
C:\path--> (Program crashes at this point)

我的代码: (我有一个头文件,但为了简单起见,我决定将所有内容都放在 .c 文件中)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
struct LinkedList {
        char* word;
        int count;
        struct LinkedList *next;
};

typedef struct LinkedList *list;
int getNextWord(char* output);
list createNode();
void addEntry(list head, char *entry);
void printList(list head);
void insert(char* dest, char* toAdd);
int compare(char* str1, char* str2);

int main(){
  int length;
  char line[5000];
  list head = NULL;
  while(length = getNextWord(line) > 0){
    printf("First word found: %s\n", line);
    addEntry(head, line);
  }
}


void addEntry(list head, char* entry){
  list temp, p;
  temp = createNode();
  if(head == NULL){
    head = temp;
    insert(head->word, entry);
    printf("head->word = %s", head->word);
    p->next->word = NULL;
    return;
  }
  else{
    p = head;
    printf("Inside else in addEntry");
    while(p->next != NULL){
      if(compare(p->word, entry) == 0){
        p->count = p->count + 1;
        return;
      }
      if(compare(p->word, entry) != 0 && p->word != NULL){
        p = p->next;
      }
      if(compare(p->word, entry) != 0 && p->word == NULL){
        insert(p->word, entry);
        p->count = p->count + 1;
        return;
      }
    }
    p->next = temp;
  }
  return;
}

/* Helper function that creates a node of type (list) */
list createNode(){
  list temp;
  temp = (list)malloc(sizeof(struct LinkedList));
  temp->next = NULL;
  return temp;
}
/*list addEntry(list head, char *entry){
  list temp, p;
  temp = createNode();
  if(head == NULL){
    printf("in addEntry head == NULL\n");
    head = temp;
    insert(head->word, entry);
  }
  else {
    printf("in first else case in addEntry\n");
    p = head;
    if((compare(entry, p->word)) == 0 && p->next != NULL){
      p->count = p->count + 1;
      while(0){
        p = p->next;
        if(p->next == NULL){
          p->next = temp;
          return;
          break;
        }
      }
    }
    else if((compare(entry, p->word) != 0 && p->next != NULL)){
        printf("in second else case in addEntry");
        p = p->next;
        addEntry(p, entry);
      }
    else if(p->word == NULL){
      insert(p->word, entry);
      p->count = p->count + 1;
      p->next = temp;
    }
    else if((compare(entry, p->word) != 0 && p->next == NULL)){
      p->next = temp;
      insert(p->word, entry);
      p->count = p->count + 1;
      p->next = NULL;

    }
  }
  return head;
}*/

void printList(list head){
  list traversal = head;
  while(traversal->next != NULL){
    printf("%s", traversal->word);
    traversal = traversal->next;
  }
}

void insert(char* dest, char* toAdd){
  strcpy(dest, toAdd);
}

int compare(char* str1, char* str2){
  int value = strcmp(str1, str2);
  return value;
}

/* I wrote this function to collect words to use */
int getNextWord(char* output){
  int c;
  int i = 0;
  while((c = getchar()) != EOF){
    if (c == ' ' || c == '\n' || c == ',')
      break;
    else{
      output[i++] = c;
    }
  }
  output[i] = '\0';
  return i;
}

【问题讨论】:

  • 现在是learn how to debug your programs 的最佳时机。不仅可以捕获和定位崩溃,还可以帮助您单步执行代码以实际查看它在做什么。
  • 欢迎来到 SO。这是开始学习如何使用调试器的好时机。你可以在 GDB 中运行你的程序,看看你的崩溃发生在哪里。
  • 另一个一般提示:不要一次做太多事情。迭代地创建您的程序,一次添加一个小功能,并在其间进行大量测试,以确保它在开始下一件事情之前可以正常工作。
  • 你知道C中的参数是按值传递的吗?你永远不会在main函数中改变head的值。
  • 顺便说一下,最好不要在length 函数中使用length 变量,因为它在循环中是不正确的。

标签: c pointers logic


【解决方案1】:

问题一:

当您创建一个新的 struct LinkedList(即在函数 createNode 中)时,您只会获得成员 word 的字符指针,并且它是未初始化的(即未指向有效内存)。

但是你这样做了:

insert(head->word, entry);

这实际上是一个字符串复制到head-&gt;word。因此,您使用未初始化的指针作为目标。那是未定义的行为。

在复制到 word 之前,您需要 malloc 一些内存(或使用 strdup 如果可用)。

问题 2:

void addEntry(list head, char* entry)

您将head 作为指针值传递。在函数内部更改head。但是,当函数返回时,您对函数内部的head 所做的任何更改都会“丢失”。换句话说 - 调用函数中的head不会被更改。这(很可能)不是你想要的。

我猜你想要:

void addEntry(list* head, char* entry)

当你这样做时,你需要在函数内部以不同的方式使用head,即*head。示例:

  if(*head == NULL){
    *head = temp;
    insert((*head)->word, entry);
    printf("head->word = %s", (*head)->word);
    // p->next->word = NULL;   REMOVE THIS LINE
    return;
  }

main中的电话

addEntry(&head, line);

顺便说一句:typedef'ing list 是一个指针通常被认为是一个坏主意。如果您真的想对指针进行类型定义,至少给它一个名称,告诉它是指针。点赞:typedef struct LinkedList *pLinkedList;

问题 3:

你永远不会初始化count。所以这里

p->count = p->count + 1;

您使用了未初始化的变量。再次未定义的行为。

问题 4:

看看这段代码:

  list temp, p;           // p is uninitialized
  temp = createNode();
  if(head == NULL){
    head = temp;
    insert(head->word, entry);
    printf("head->word = %s", head->word);
    p->next->word = NULL;   // Here p is used but it still uninitialized !!
    return;
  }

这又是未定义的行为

【讨论】:

  • 您好,非常感谢您的快速反馈。我通过将其设为 word[50] 来初始化结构中的 word,并通过设置 temp->count -0; 在 createNode() 中计数。此外,我可以看到程序不再立即崩溃。但是,我添加了一种在输入“停止”时停止输入的方法,这会使程序崩溃。我不确定如何处理 addEntry,因为当我将其更改为 list* head 而不是 list head 时,我遇到了更多错误。对不起,我是一个菜鸟,我才刚刚开始学习。关于第四个问题,我本想输入head,但我错误地输入了p。
  • @AbdulazizAl-Boainain 我添加了一些额外的解释
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-14
  • 1970-01-01
  • 2020-11-06
  • 2013-05-29
  • 1970-01-01
相关资源
最近更新 更多