You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 06:32:13