C语言strtok函数原理与自定义实现指南

慢慢来
慢慢来
发布时间:2026-10-16| 4人浏览过
原创

在使用C语言进行字符串处理时,strtok 是常见的分割工具。由于其会在原始字符串中插入结束符 '\0' 并依赖静态全局变量记录状态,因此在实际开发中存在线程不安全及破坏源数据的限制。本文将深入剖析 strtok 的运行原理,展示其标准用法,并提供一份完整的自定义实现代码。

一、strtok 函数的基本使用与注意事项

strtok 用于将字符串按指定的分隔符拆分为多个子串。在使用该函数时,必须明确两个核心要点:一是它具备副作用,二是它的状态管理机制。

使用要点解析:

  1. 修改原字符串:调用后,目标字符串中的分隔符位置会被替换为 '\0'。如果后续还需保留原文,必须先使用 strcpy 等函数创建副本后再进行分割。
  2. 分隔符定义:第二个参数 delimiters 是一个包含所有分隔符的字符数组。例如,若空格和制表符均需作为分隔符,则定义:char delimiters[] = " \t"。
  3. 首次调用:传入待分割的字符串指针和分隔符。strtok 会查找第一个标记,将其返回,并将内部静态指针指向该标记后的下一个字符(即被 '\0' 覆盖处的下一位)。
  4. 后续调用:为了继续获取下一个标记,第一个参数必须传入 NULL。函数将利用内部保存的位置继续向后搜索。
  5. 结束条件:当字符串中不再存在未处理的标记时,函数返回 NULL。

以下是一段标准的分割示例代码,展示了如何将文本存入数组并遍历打印:

int main()
{
	// 注意:strtok会修改字符串,建议操作副本
	char a[] = "wo shi bo zhu";
	char* retArr[10]; // 存储分割后的子串指针
	
	retArr[0] = strtok(a, " "); // 第一次分割,指定分隔符为空格
	int i = 1;
	// 循环接收后续结果,直到返回NULL
	while (retArr[i++] = strtok(NULL, " "));
	
	for (int j = 0; j < i - 1; j++)
	{
		printf("%s \n", retArr[j]);
	}
	return 0;
}

二、strtok 的内部实现原理分析

要实现一个等效于 strtok 的函数,关键在于如何模拟其“记忆”功能。在C语言中,通常使用 static 修饰的局部指针变量来保存上一次执行结束的位置信息。

核心逻辑设计:

  • 状态保存:声明静态指针 static char* p_last = NULL;。如果当前不是第一次调用且传入了 NULL,则从 p_last 处开始扫描;否则从头部的 str 开始。
  • 扫描匹配:使用临时指针 tmp 逐个检查字符是否在分隔符列表中。找到分隔符时,将其覆盖为 '\0' 以截断子串,同时将 p_last 更新为当前位置的下一字节。
  • 收尾处理:如果遍历完整个字符串仍未找到分隔符(说明这是最后一个子串),应将 p_last 重置为 NULL,防止下次重复调用出错。

第1步:准备测试环境与数据

首先构建一段带有空格的测试字符串,并使用与我们即将编写的 my_strtok 相同的调用接口进行测试。

第2步:首次进入函数处理逻辑

传入有效字符串时,函数定位起始位置,跳过无效前缀(如果有),遇到第一个分隔符进行截断并记录状态。

第3步:后续多次调用的流转过程

当再次调用传入 NULL 时,指针接管上一次的遗留位置,继续向后查找。

第4步:到达末尾的终止判断

当指针扫过最后一个字符且找不到分隔符时,正确返回最后一个子串并清空内部静态指针。

三、完整自定义实现代码

以下是符合上述逻辑的分析实现的完整代码,可直接编译运行验证:

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

char* my_strtok(char* str, const char* delimiters)
{
	// 静态变量用于保存上次扫描的剩余部分
	static char* p_last = NULL;
	
	// 情况1:既没有新字符串,也没有历史记录,直接返回空
	if (str == NULL && p_last == NULL)
		return NULL;
	
	// 如果没有新字符串但有历史记录,沿用上次断点
	if (str == NULL)
	{
		str = p_last;
	}
	
	char* tmp = str;
	size_t len = strlen(delimiters);
	
	// 循环扫描字符,寻找分隔符
	while (*tmp)
	{
		for (size_t i = 0; i < len; ++i)
		{
			if (*tmp == delimiters[i])
			{
				// 找到分隔符:截断字符串,更新断点
				p_last = tmp + 1;
				*tmp = '\0';
				return str;
			}
		}
		tmp++; // 移动指针继续查找
	}
	
	// 走到这里表示字符串剩余部分无更多分隔符了
	char* ret = p_last;
	p_last = NULL; // 标记已结束,防止下次误用
	return ret;
}

// 测试主函数
int main()
{
	char a[] = "wo ai ni";
	char* retArr[10];
	
	retArr[0] = my_strtok(a, " ");
	int i = 1;
	
	while (retArr[i++] = my_strtok(NULL, " "));
	
	for (int j = 0; j < i - 1; j++)
	{
		printf("%s \n", retArr[j]);
	}
	
	return 0;
}

以上就是的详细内容,更多关于的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。