在C语言中,没有内置的字符串分割函数(如Python的split()或Java的split()),但我们可以手动实现一个字符串分割函数,以下是几种实现方式,从简单到复杂,并附有详细解释。

(图片来源网络,侵删)
方法1:使用strtok函数(标准库方法)
strtok是C标准库<string.h>提供的函数,用于分割字符串,它会修改原字符串(用\0替换分隔符),并且不是线程安全的。
示例代码
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "apple,banana,orange,grape";
const char *delim = ","; // 分隔符
char *token;
// 第一次调用,传入字符串和分隔符
token = strtok(str, delim);
while (token != NULL) {
printf("%s\n", token);
// 后续调用,传入NULL,表示继续分割上一次的字符串
token = strtok(NULL, delim);
}
return 0;
}
输出
apple
banana
orange
grape
注意事项
strtok会修改原字符串(用\0替换分隔符)。- 如果需要保留原字符串,可以先复制一份再分割。
strtok不是线程安全的(多线程环境下可能有问题)。- 连续的分隔符会被视为一个分隔符(
"a,,b"会被分割成"a"和"b")。
方法2:手动实现字符串分割(不修改原字符串)
如果不想修改原字符串,或者需要更灵活的控制(如处理连续分隔符、转义字符等),可以手动实现分割函数。
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 分割字符串,返回动态分配的字符串数组
char** split_string(const char *str, const char *delim, int *count) {
if (str == NULL || delim == NULL) {
*count = 0;
return NULL;
}
// 计算分割后的子串数量
int delim_len = strlen(delim);
int temp_count = 0;
const char *p = str;
while ((p = strstr(p, delim)) != NULL) {
temp_count++;
p += delim_len;
}
*count = temp_count + 1; // 最后一个子串后面没有分隔符
// 分配内存存储子串指针
char **result = (char**)malloc((*count) * sizeof(char*));
if (result == NULL) {
*count = 0;
return NULL;
}
// 逐个分割子串
p = str;
for (int i = 0; i < *count; i++) {
const char *next_delim = strstr(p, delim);
int len;
if (next_delim == NULL) {
len = strlen(p);
} else {
len = next_delim - p;
}
// 分配内存并复制子串
result[i] = (char*)malloc(len + 1);
strncpy(result[i], p, len);
result[i][len] = '\0';
if (next_delim == NULL) {
break;
}
p = next_delim + delim_len;
}
return result;
}
// 释放分割后的内存
void free_split_result(char **result, int count) {
if (result == NULL) return;
for (int i = 0; i < count; i++) {
free(result[i]);
}
free(result);
}
int main() {
const char *str = "apple,banana,orange,grape";
const char *delim = ",";
int count;
char **tokens = split_string(str, delim, &count);
if (tokens != NULL) {
for (int i = 0; i < count; i++) {
printf("%s\n", tokens[i]);
}
free_split_result(tokens, count);
}
return 0;
}
输出
apple
banana
orange
grape
特点
- 不修改原字符串:使用
strncpy复制子串。 - 动态内存管理:调用者需要手动释放内存(
free_split_result)。 - 支持任意分隔符(如 或
"->")。 - 处理连续分隔符(
"a,,b"会被分割成"a"和 和"b")。
方法3:使用strtok_r(线程安全版本)
如果需要线程安全的分割,可以使用POSIX标准提供的strtok_r(非Windows平台可用)。
示例代码
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "apple,banana,orange,grape";
const char *delim = ",";
char *token;
char *saveptr; // 用于保存上下文
// 第一次调用,传入字符串和分隔符
token = strtok_r(str, delim, &saveptr);
while (token != NULL) {
printf("%s\n", token);
// 后续调用,传入NULL和saveptr
token = strtok_r(NULL, delim, &saveptr);
}
return 0;
}
输出
apple
banana
orange
grape
特点
- 线程安全:通过
saveptr保存上下文,避免多线程冲突。 - 仍然修改原字符串(用
\0替换分隔符)。
| 方法 | 是否修改原字符串 | 线程安全 | 适用场景 |
|---|---|---|---|
strtok |
是 | 否 | 简单分割,单线程 |
| 手动实现 | 否 | 是 | 需要保留原字符串,或复杂逻辑 |
strtok_r |
是 | 是 | 多线程环境 |
推荐选择
- 如果只是简单分割且不关心线程安全,用
strtok。 - 如果需要保留原字符串或更灵活的控制,手动实现。
- 如果是多线程环境,用
strtok_r(POSIX平台)。
希望这能帮到你!如果有更具体的需求(如处理转义字符、空格分割等),可以进一步优化代码。

(图片来源网络,侵删)
