链表回文判断代码出现段错误,求排查与修复方案
链表回文判断程序的段错误排查与修复
问题概述
需要实现一个程序判断双向链表是否为回文结构,输入要求为:
- 第一行:空格分隔的整数(链表元素)
- 第二行:单个整数(链表长度)
输出要求:是回文则输出Palindrome,否则输出Not Palindrome。
用户实现的创建链表和回文判断函数出现段错误,附带代码及编译器警告如下:
用户原代码
//The function for creating the nodes using array. struct node* create(head){ int n; printf("Enter the number of nodes in the linked list:"); scanf("%d", &n); int arr[n]; printf("Enter the character for each node spearated by spaces:"); for(int i=0; i<n; i++){ fscanf(stdin,"%d", &arr[i]); } for(int i=0;i<n;i++){ struct node* temp = (struct node*)malloc(sizeof(struct node)); temp->data = arr[i]; temp->next = NULL; temp->prev=NULL; struct node* p; if(head==NULL){ head=temp; } else{ while (p->next!=NULL) { p=p->next; } p->next=temp; temp->prev=p; } } } //The function for checking palindrome struct node* pallindrome(head){ struct node* p = head; struct node* q = head; int count=0; while(q!=NULL){ q=q->next; count++; } for(int i=0;i<(count/2);i++){ if(p->data==q->data){ p=p->next; q=q->prev; continue; } else{ printf("Not Pallindrome"); return; } } printf("Pallindrome"); }
编译器警告信息
pallindrome.c: In function 'create': pallindrome.c:13:14: warning: type of 'head' defaults to 'int' [-Wimplicit-int] struct node* create(head){ ^~~~~~ pallindrome.c:28:16: warning: comparison between pointer and integer if(head==NULL){ ^~ pallindrome.c:29:17: warning: assignment makes integer from pointer without a cast [-Wint-conversion] head=temp; ^ pallindrome.c: In function 'pallindrome': pallindrome.c:42:14: warning: type of 'head' defaults to 'int' [-Wimplicit-int] struct node* pallindrome(head){ ^~~~~~~~~~~ pallindrome.c:43:22: warning: initialization makes pointer from integer without a cast [-Wint-conversion] struct node* p = head; ^~~~ pallindrome.c:44:22: warning: initialization makes pointer from integer without a cast [-Wint-conversion] struct node* q = head; ^~~~ pallindrome.c:59:13: warning: 'return' with no value, in function returning non-void return; ^~~~~~ pallindrome.c:42:14: note: declared here struct node* pallindrome(head){ ^~~~~~~~~~~
错误分析与修复步骤
1. 函数参数类型缺失引发的类型错误
- 问题:
create和pallindrome函数的head参数未声明类型,C语言默认将其视为int类型,导致指针与整数的非法转换(如把struct node*赋值给int,用int初始化指针),直接引发地址访问错误。 - 修复:给
head参数添加正确的类型struct node*;create函数采用返回头指针的方式,避免二级指针的复杂操作。
2. 未初始化指针导致的段错误
- 问题:
create函数的else分支中,指针p未初始化就直接访问p->next,属于未定义行为,必然触发段错误。 - 修复:改用
tail指针记录链表尾部,直接追加新节点,无需每次遍历到尾部,既解决未初始化问题,又提升效率。
3. 函数未返回值导致的非法访问
- 问题:
create函数声明返回struct node*,但函数末尾无return语句,外部调用时会拿到垃圾值,访问链表时引发段错误;pallindrome函数声明返回struct node*,但实际无需返回值,return;语句会导致未定义行为。 - 修复:
create函数末尾添加return head;;将pallindrome函数的返回类型改为void,移除无意义的返回值。
4. 回文判断逻辑错误
- 问题:遍历链表时
q最终指向NULL,此时访问q->data或q->prev属于非法内存访问;计数逻辑也因q到NULL导致多算一个节点。 - 修复:调整遍历逻辑,让
q停在最后一个节点(而非NULL),再进行首尾对比。
5. 输入逻辑不符合题目要求
- 问题:原
create函数内部读取长度和元素,与题目“先输入元素、再输入长度”的要求不符,且耦合性高。 - 修复:将输入逻辑移到
main函数中,按照题目要求读取数据后,传入create函数创建链表。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> // 定义双向链表节点结构 struct node { int data; struct node* next; struct node* prev; }; // 创建双向链表:接收元素数组和长度,返回头指针 struct node* create(int arr[], int n) { struct node* head = NULL; struct node* tail = NULL; // 用tail记录尾部,避免重复遍历 for (int i = 0; i < n; i++) { struct node* temp = (struct node*)malloc(sizeof(struct node)); temp->data = arr[i]; temp->next = NULL; temp->prev = NULL; if (head == NULL) { head = temp; tail = temp; } else { tail->next = temp; temp->prev = tail; tail = temp; // 更新尾部指针 } } return head; } // 判断链表是否为回文 void is_palindrome(struct node* head) { if (head == NULL) { printf("Palindrome\n"); return; } struct node* p = head; struct node* q = head; // 移动q到最后一个节点 while (q->next != NULL) { q = q->next; } int count = 0; struct node* temp = head; // 统计链表节点数 while (temp != NULL) { count++; temp = temp->next; } // 首尾对比一半节点 for (int i = 0; i < count / 2; i++) { if (p->data != q->data) { printf("Not Palindrome\n"); return; } p = p->next; q = q->prev; } printf("Palindrome\n"); } int main() { // 按照题目要求读取输入 int n; int arr[100]; // 假设最大节点数为100,可根据需求调整 // 读取第一行元素 printf("Enter the linked list elements separated by spaces: "); int i = 0; while (scanf("%d", &arr[i]) == 1) { i++; // 处理换行符,判断是否到第二行 char c = getchar(); if (c == '\n') break; } // 读取第二行的长度 printf("Enter the length of the linked list: "); scanf("%d", &n); struct node* head = create(arr, n); is_palindrome(head); // 释放链表内存,避免内存泄漏 struct node* current = head; while (current != NULL) { struct node* next = current->next; free(current); current = next; } return 0; }
说明
- 修复后的代码解决了所有编译器警告和段错误问题,完全符合题目输入输出要求。
- 添加了内存释放逻辑,避免程序运行时的内存泄漏。
- 优化了链表创建效率,使用
tail指针直接追加节点,无需每次遍历到尾部。
内容的提问来源于stack exchange,提问作者Mridul Hemrajani
相关产品推荐
相关产品推荐

