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; }
关键细节说明
为什么要复制原字符串?
strtok函数会直接修改传入的字符串(把分隔符替换为\0),如果原字符串需要保留,必须先复制一份,这里用strdup完成,它会自动分配内存并复制字符串内容。动态数组的扩容逻辑
初始给数组设置一个小容量(比如4),当子串数量达到容量上限时,用realloc把容量翻倍。这种方式既不会浪费过多内存,又能减少扩容次数,兼顾效率和内存利用率。内存安全保障
每次分配内存后都要检查是否成功,如果失败,一定要把已经分配的内存全部释放,避免内存泄漏问题。strtok的适配性
strtok会自动忽略字符串开头的空白字符,并且连续的空白字符会被当作一个分隔符,完美匹配你的需求——比如输入开头的空格会被跳过,连续的空格/制表符也不会产生空的子串。
可选优化
如果你的程序运行在多线程环境中,建议用strtok_r(线程安全版本)替代strtok,用法和strtok类似,只是多了一个保存上下文的参数,避免线程间的干扰。
内容的提问来源于stack exchange,提问作者Programmer666
相关产品推荐
相关产品推荐

