C语言 链表分段故障



我正在练习写一个链表,它将从用户那里按升序获取数字,并告诉您使用的唯一数字是什么。在它索引我的findUnique函数和我的while循环之后,我一直得到一个分割错误,我已经设置了在它进入不打印任何东西之前打印列表。这只是链表的练习,所以任何帮助都会很感激。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct number{
    int num;
    struct number* next;
}Number;
Number *addterm(Number*, int);
void findUnique(Number*);
int main(void){
    Number *Number_List = NULL;
    int digit = 1;
    printf("Enter numbers in ascending order(enter 0 to stop): ");
    scanf("%d", &digit);
    while(digit != 0){
        addterm(Number_List, digit);
        printf("Enter numbers in ascending order(enter 0 to stop): ");
        scanf("%d", &digit);
    }
    printf("ntest 1n");
    Number *ptr = Number_List;
    while(ptr){
        printf("%d ", ptr -> num);  
        Number_List = ptr -> next;          
    }
    printf("ntest 2n");
    printf("n");
    findUnique(Number_List);

    return 0;
}
Number *addterm(Number* list, int userIn){
    Number *newNum = (Number *) malloc ( sizeof (Number) );
    newNum->num = userIn;
    newNum->next = list;
    if(list == NULL){
        return newNum;
    }
    Number *ptr = list;
    while( ptr->next != NULL ){
        ptr = ptr->next;
    }
    ptr->next = newNum;
    return list;
}
void findUnique(Number* list){
    int print, temp;
    print = list->num;
    temp = print;
    printf("The unique numbers you entered are %d", temp);
    while( list ){
        print = list->num;
        if(print == temp){
            continue;
        }
        else{
        temp = print;
        printf(" %d", temp);
        }
        list = list -> next;
    }
    return;
}

错误1:

addterm(Number_List, digit);

应为

Number_List = addterm(Number_List, digit);

你忘记更新列表指针了

错误2:

while(ptr){
    printf("%d ", ptr -> num);  
    Number_List = ptr -> next;          
}

应为

while(ptr){
    printf("%d ", ptr -> num);  
    ptr = ptr -> next;          
}

这会产生一个无限循环。

错误3:

newNum->next = list;  //In addTerm()

应为

newNum->next = NULL;

新节点没有下一个节点集。这也产生了一个无限循环。

错误4:

if(print == temp){
        continue;
}

应为

if(print == temp){
        list = list->next;
        continue;
    }

另一个无限循环

我尝试过这个问题,我认为错误是在您的findUnique函数中。下面的@MatzZze已经涵盖了这些问题,它将帮助修复您当前的代码。

或者,您可以尝试这种方法。它展示了从链表中删除重复项的另一种方法,并适当地更新链表。我所包含的额外代码只是为了帮助运行程序。

在这里:

#include <stdio.h>
#include <stdlib.h>
typedef int data_t;
typedef struct node node_t;
struct node {
    data_t num;
    node_t *next;
};
typedef struct {
    node_t *head;
    node_t *foot;
}list_t;
list_t *make_empty_list(void);
list_t *add_term(list_t *list, data_t value);
void read_terms(list_t *list);
void print_unique_terms(list_t *list);
list_t *unique_terms(list_t *list);
void print_list(list_t *list);
void free_list(list_t *list);
int
main(int argc, char const *argv[]) {
    list_t *list;
    list = make_empty_list();
    read_terms(list);
    printf("Your numbers are:n");
    print_list(list);
    unique_terms(list);
    printf("The unique numbers you entered are:n");
    print_list(list);
    free(list);
    return 0;
}
void
read_terms(list_t *list) {
    int digit;
    printf("Enter numbers in ascending order(enter 0 to stop): ");
    while (scanf("%d", &digit) == 1) {
        if (digit == 0) {
            break;
        } else {
            add_term(list, digit);
        }
    }
}
list_t
*add_term(list_t *list, data_t value) {
    node_t *node;
    node = malloc((sizeof(*node)));
    node->num = value;
    node->next = NULL;
    if (list->foot == NULL) {
        list->head = list->foot = node;
    } else {
        list->foot->next = node;
        list->foot = node;
    }
    return list;
}
list_t
*unique_terms(list_t *list) {
    node_t *node = list->head;
    while (node != NULL && node->next != NULL) {
        if (node->num == node->next->num) {
            node->next = node->next->next;
        } else {
            node = node->next;
        }
    }
    return list;
}
void
free_list(list_t *list) {
    node_t *curr, *prev;
    curr = list->head;
    while (curr) {
        prev = curr;
        curr = curr->next;
        free(prev);
    }
    free(list);
}
void
print_list(list_t *list) {
    node_t *node = list->head;
    while (node != NULL) {
        printf("%d ", node->num);
        node = node->next;
    }
    printf("n");
 }
list_t
*make_empty_list(void) {
     list_t *list;
     list = malloc(sizeof(*list));
     list->head = NULL;
     list->foot = NULL;
     return list;
}

这些都是很棒的答案,它们肯定会帮助您完成这段代码。

然而,我建议如下:这个问题的真正答案是,这是一个链表,你可能知道:

+------+     +------+     +------+
| data |     | data |     | data |
+------+     +------+     +------+
| next |---->| next |---->| next |----> NULL
+------+     +------+     +------+
   ^
   |
 START (Keep track of the whole list.)

你可能遇到的最大危险是你的next和start指针。现在来回答你的问题,用一种能帮助你做以下事情的方式:

  1. 在IDE中启用调试,并在程序入口点设置断点。在快速射击中使用Step over工具,直到程序出错。现在你知道是哪一行引起的了。

  2. 在该行上放置一个断点,并调试到该点,并确定何时设置导致问题的指针。

  3. 许多IDE提供了一个工具,可以在变量上放置一个"监视",只有当您指定的变量等于您指定的值时,才会在某个点中断程序,在这种情况下,我建议为NULL。

  4. 因为现在你得到分段错误,你需要看看你有循环的地方,因为你可能迭代超过你的列表的界限。

学习调试技术才是解决这个问题的正确方法!

祝你好运!

最新更新