C语言双向链表字符串转大写程序运行异常问题排查
C语言双向链表字符串大写转换执行异常修复
核心问题点
- 直接修改字符串字面量触发内存访问错误:代码中传入
insertAtEnd的"Orange"、"banana"、"PEAR"属于字符串字面量,C标准中字符串字面量存储在只读内存区域,任何对该区域内容的写操作都会触发段错误,导致程序直接终止。你看到仅打印一次Entered outer loop就退出,是因为第一次循环处理首字符'O'为大写,没有触发写操作;循环到第二个字符'r'时执行赋值修改,直接触发崩溃,后续逻辑完全不会执行。你加的类型强转完全不涉及内存权限问题,因此无法修复故障。 - 转换逻辑未遍历全链表:现有转换循环仅处理头节点
head的data字符串,即使内存可写,也只会转换第一个节点的内容,后两个节点的字符串完全不会被处理,达不到全链表转换的目标。
修正步骤
- 引入
<string.h>头文件,修改insertAtEnd的实现:插入节点时为字符串动态申请可写的堆内存,将传入的字符串内容拷贝到新申请的内存中,避免直接指向只读的字符串字面量。 - 重构大写转换逻辑:先遍历双向链表的所有节点,再对每个节点存储的字符串逐字符判断、转换,覆盖所有节点的所有字符。
修正后完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> // 双向链表节点结构 struct node { char* data; struct node *prev; struct node *next; }; struct node* head = NULL; struct node* tail = NULL; // 尾插法插入节点 void insertAtEnd(char* data) { struct node *newNode = (struct node*)malloc(sizeof(struct node)); // 为字符串申请可写内存,长度为字符串长度+1(存储结束符'\0') size_t data_len = strlen(data); newNode->data = (char*)malloc(data_len + 1); // 拷贝字符串内容到可写内存 strcpy(newNode->data, data); if(head == NULL) { head = tail = newNode; head->prev = NULL; tail->next = NULL; } else { tail->next = newNode; newNode->prev = tail; tail = newNode; tail->next = NULL; } } // 遍历链表打印内容 void traverse() { if (head == NULL) { printf("\nList is empty\n"); return; } struct node* temp = head; while (temp != NULL) { printf("%s\n", temp->data); temp = temp->next; } } int main(int argc, char **argv){ insertAtEnd("Orange"); insertAtEnd("banana"); insertAtEnd("PEAR"); // 遍历所有节点做大写转换 struct node* curr = head; while (curr != NULL) { // 逐字符处理当前节点的字符串 for (int i = 0; curr->data[i]!='\0'; i++) { printf("Entered outer loop\n"); // 小写字母ASCII范围97~122,减32转大写 if(curr->data[i] >= 97 && curr->data[i] <= 122) { curr->data[i] = curr->data[i] - 32; printf("Entered inner loop\n"); } } curr = curr->next; } traverse(); // 注意:生产环境需要遍历释放所有节点的data和节点本身内存,避免内存泄漏,此处为复现逻辑简化省略 return 0; }
运行预期输出
// 省略循环过程的日志打印 ORANGE BANANA PEAR
内容的提问来源于stack exchange,提问作者Ale
相关产品推荐
相关产品推荐

