C语言链表分割点分隔字符串:乱码与末尾节点未打印问题求助
问题描述
需要用链表实现按.分隔字符串并打印各子串,目前遇到两个问题:
- 打印的子串中出现异常乱码字符
- 最后一个节点无法打印,找不到添加该节点的方法
以下是我的代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct node { char *word; struct node *next; }node_t; node_t *split_string(char *str) { int i=0,j=0; int k=0; int count=0; node_t *head=NULL, *tmp=NULL, *p=NULL; char buffer[20]; for(i=0;i<strlen(str);i++) { if(str[i]!='.') count++; else { for(j=i-count;j<i;j++) { buffer[k]=str[j]; k++; } k=0; count=0; tmp=(node_t*)malloc(sizeof(node_t)); if(tmp == NULL) { exit(1); } tmp->next=NULL; tmp->word=strdup(buffer); if(tmp->word == NULL) { exit(2); } if(head == NULL) { head=tmp; } else { p=head; while(p->next != NULL) // 我知道这里可能有问题,但改成while(p != NULL)的话就什么都打不出来 { p=p->next; } p->next=tmp; } } } return head; } void printList(node_t *head) { node_t *tmp=head; int i=1; while(tmp != NULL) { printf("Node %d -> %s\n",i,tmp->word); tmp=tmp->next; i++; } } int main() { char str[]={"aaa.sss.ddd.aaa.ddd.ddd"}; node_t *head=NULL; head=split_string(str); printList(head); return 0; }
问题分析与修复
1. 乱码问题的解决
原因:buffer是栈上的字符数组,填充子串后未添加字符串结束符\0,strdup会从buffer起始位置一直读取内存直到遇到\0,导致读取到栈上的垃圾数据,表现为乱码。
修复:每次填充完buffer后手动添加字符串结束符,在else块的k=0;之前插入一行:
buffer[k] = '\0'; // 为buffer添加字符串结束标记
修改后的else块片段:
else { for(j=i-count;j<i;j++) { buffer[k]=str[j]; k++; } buffer[k] = '\0'; // 新增:添加结束符 k=0; count=0; // 后续创建节点的代码不变... }
2. 最后一个节点无法打印的解决
原因:原代码仅在遇到.时才创建节点并添加到链表,但最后一个子串后面没有.,循环结束后这段子串未被处理,因此无法添加到链表。
修复:在for循环结束后,检查count的值,如果count>0,说明还有最后一段子串未处理,重复创建节点的逻辑将其添加到链表:
在split_string函数的return head;之前插入以下代码:
// 处理最后一段没有.结尾的子串 if(count > 0) { k = 0; for(j = strlen(str)-count; j < strlen(str); j++) { buffer[k] = str[j]; k++; } buffer[k] = '\0'; // 同样要添加结束符 tmp=(node_t*)malloc(sizeof(node_t)); if(tmp == NULL) { exit(1); } tmp->next=NULL; tmp->word=strdup(buffer); if(tmp->word == NULL) { exit(2); } if(head == NULL) { head=tmp; } else { p=head; while(p->next != NULL) { p=p->next; } p->next=tmp; } }
另外说明:你原来的链表遍历逻辑while(p->next != NULL)是正确的,它能找到链表的最后一个节点;如果改成while(p != NULL),循环结束后p会变成NULL,此时访问p->next会导致空指针错误,所以不需要修改这段逻辑。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct node { char *word; struct node *next; }node_t; node_t *split_string(char *str) { int i=0,j=0; int k=0; int count=0; node_t *head=NULL, *tmp=NULL, *p=NULL; char buffer[20]; for(i=0;i<strlen(str);i++) { if(str[i]!='.') count++; else { for(j=i-count;j<i;j++) { buffer[k]=str[j]; k++; } buffer[k] = '\0'; // 添加字符串结束符 k=0; count=0; tmp=(node_t*)malloc(sizeof(node_t)); if(tmp == NULL) { exit(1); } tmp->next=NULL; tmp->word=strdup(buffer); if(tmp->word == NULL) { exit(2); } if(head == NULL) { head=tmp; } else { p=head; while(p->next != NULL) { p=p->next; } p->next=tmp; } } } // 处理最后一个子串 if(count > 0) { k = 0; for(j = strlen(str)-count; j < strlen(str); j++) { buffer[k] = str[j]; k++; } buffer[k] = '\0'; tmp=(node_t*)malloc(sizeof(node_t)); if(tmp == NULL) { exit(1); } tmp->next=NULL; tmp->word=strdup(buffer); if(tmp->word == NULL) { exit(2); } if(head == NULL) { head=tmp; } else { p=head; while(p->next != NULL) { p=p->next; } p->next=tmp; } } return head; } void printList(node_t *head) { node_t *tmp=head; int i=1; while(tmp != NULL) { printf("Node %d -> %s\n",i,tmp->word); tmp=tmp->next; i++; } } int main() { char str[]={"aaa.sss.ddd.aaa.ddd.ddd"}; node_t *head=NULL; head=split_string(str); printList(head); return 0; }
内容的提问来源于stack exchange,提问作者Severjan Lici
相关产品推荐
相关产品推荐

