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

C语言:如何分割含空格、制表符的字符串并动态创建子串数组?

解决含空白字符的字符串分割与动态子串存储问题

嘿,我完全懂你遇到的困扰——要处理混着空格和制表符的字符串,提取数量不定的子串,原本想用动态数组来存结果却卡在了malloc的实现上。别慌,我给你一套清晰的C语言实现方案,完美匹配你的需求。

核心思路

我们分两步解决问题:

  • 分割字符串:把输入字符串按空格、制表符这类空白字符拆分成独立子串
  • 动态存储:用可扩容的字符串数组保存子串,避开固定大小数组的局限性

完整实现代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    // 你的输入字符串,包含空格和制表符
    char input[] = " abc 	 tt 6 	 4 7";
    // 先复制原字符串,因为strtok会直接修改原串内容
    char* str_copy = strdup(input);
    if (str_copy == NULL) {
        perror("strdup分配内存失败");
        return 1;
    }

    // 初始化动态字符串数组
    char** tokens = NULL;
    size_t token_count = 0;
    size_t capacity = 4; // 初始容量,可根据实际需求调整

    // 第一次为数组分配内存
    tokens = malloc(capacity * sizeof(char*));
    if (tokens == NULL) {
        perror("malloc分配数组内存失败");
        free(str_copy);
        return 1;
    }

    // 用strtok分割字符串,分隔符为空格和制表符
    char* token = strtok(str_copy, " \t");
    while (token != NULL) {
        // 数组容量不足时,扩容(这里采用翻倍策略,平衡内存占用和扩容效率)
        if (token_count >= capacity) {
            capacity *= 2;
            char** temp = realloc(tokens, capacity * sizeof(char*));
            if (temp == NULL) {
                perror("realloc扩容失败");
                // 扩容失败时,必须清理已分配的所有内存
                for (size_t i = 0; i < token_count; i++) {
                    free(tokens[i]);
                }
                free(tokens);
                free(str_copy);
                return 1;
            }
            tokens = temp;
        }

        // 复制子串到数组中,strdup会自动为子串分配内存
        tokens[token_count] = strdup(token);
        if (tokens[token_count] == NULL) {
            perror("strdup复制子串失败");
            // 出错时清理已分配资源
            for (size_t i = 0; i < token_count; i++) {
                free(tokens[i]);
            }
            free(tokens);
            free(str_copy);
            return 1;
        }

        token_count++;
        // 继续分割剩余的字符串
        token = strtok(NULL, " \t");
    }

    // 打印提取结果,验证是否符合预期
    printf("提取到的子串:\n");
    for (size_t i = 0; i < token_count; i++) {
        printf("str%zu = \"%s\"\n", i+1, tokens[i]);
    }

    // 释放所有动态分配的内存,避免内存泄漏
    for (size_t i = 0; i < token_count; i++) {
        free(tokens[i]);
    }
    free(tokens);
    free(str_copy);

    return 0;
}

关键细节说明

  1. 为什么要复制原字符串?
    strtok函数会直接修改传入的字符串(把分隔符替换为\0),如果原字符串需要保留,必须先复制一份,这里用strdup完成,它会自动分配内存并复制字符串内容。

  2. 动态数组的扩容逻辑
    初始给数组设置一个小容量(比如4),当子串数量达到容量上限时,用realloc把容量翻倍。这种方式既不会浪费过多内存,又能减少扩容次数,兼顾效率和内存利用率。

  3. 内存安全保障
    每次分配内存后都要检查是否成功,如果失败,一定要把已经分配的内存全部释放,避免内存泄漏问题。

  4. strtok的适配性
    strtok会自动忽略字符串开头的空白字符,并且连续的空白字符会被当作一个分隔符,完美匹配你的需求——比如输入开头的空格会被跳过,连续的空格/制表符也不会产生空的子串。

可选优化

如果你的程序运行在多线程环境中,建议用strtok_r(线程安全版本)替代strtok,用法和strtok类似,只是多了一个保存上下文的参数,避免线程间的干扰。

内容的提问来源于stack exchange,提问作者Programmer666

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:29:09