当前位置: 首页 > news >正文

C语言strtok()函数用法详解!

strtok 是 C 标准库中的字符串分割函数,用于将一个字符串拆分成多个部分(token),以某些字符(称为分隔符)为界限。


函数原型

char *strtok(char *str, const char *delim);
  • 参数

    • str:待分割的字符串。如果是第一次调用,传入要分割的字符串;之后的调用需传入 NULL,以继续上一次的分割。
    • delim:字符串,包含所有分隔符的字符集合。例如," "(空格)或 "/"(斜杠)
  • 返回值

    • 返回指向字符串中 当前部分 的指针。
    • 如果没有更多部分可返回,返回 NULL

用法规则

  1. 初次调用时,传入字符串 str,函数会从 str 中找到第一个部分。
  2. 函数会用 '\0' 替换找到的分隔符(破坏原字符串)。
  3. 后续调用时,传入 NULL,函数会继续从上次结束的位置查找下一部分。
  4. 不能在多线程环境中使用,因为 strtok 使用的是静态变量保存状态。

示例

#include <stdio.h>
#include <string.h>int main() {char str[] = "C programming is fun";const char *delim = " "; // 用空格作为分隔符char *token;// 初次调用 strtoktoken = strtok(str, delim);while (token != NULL) {printf("%s\n", token); // 打印分割的每一部分token = strtok(NULL, delim); // 后续调用}return 0;
}

输出

C
programming
is
fun

注意事项

  1. 原字符串被修改strtok 会在分隔符处插入 '\0',因此原字符串内容会被破坏。如果需要保留原字符串,请先复制到一个新字符串再操作。

  2. 不能并发使用:由于 strtok 使用内部静态变量保存状态,它在多线程程序中不安全。多线程环境下,请使用 strtok_r


分隔符的处理

分隔符 delim 可以包含多个字符,strtok 会将所有出现在 delim 中的字符视为分隔符。例如:

#include <stdio.h>
#include <string.h>int main() {char str[] = "apple;orange,banana|grape";const char *delim = ";,|"; // 多个分隔符char *token;token = strtok(str, delim);while (token != NULL) {printf("%s\n", token);token = strtok(NULL, delim);}return 0;
}

输出

apple
orange
banana
grape

如何在多线程中使用?

在多线程环境下,使用 strtok_r(线程安全版本)。函数原型如下:

char *strtok_r(char *str, const char *delim, char **saveptr);

参数说明

  • str:首次调用传入要分割的字符串,后续调用传入 NULL
  • delim:分隔符集合。
  • saveptr:保存分割状态的指针变量,需由调用者提供。

示例

#include <stdio.h>
#include <string.h>int main() {char str[] = "apple;orange,banana|grape";const char *delim = ";,|";char *token;char *saveptr; // 保存状态token = strtok_r(str, delim, &saveptr);while (token != NULL) {printf("%s\n", token);token = strtok_r(NULL, delim, &saveptr);}return 0;
}

输出

apple
orange
banana
grape

为什么需要传入 NULL

strtok 函数内部使用了一个 静态指针 来记录分割状态。这个静态指针会指向原字符串中上一次分割结束的位置。在首次调用时,strtok 初始化这个指针为传入的字符串地址。在后续调用时,通过传入 NULLstrtok 会继续从这个内部静态指针的位置接着分割。


静态指针的工作原理

  1. 初次调用

    token = strtok(str, delim);
    
    • 参数 str 是待分割字符串。
    • strtok 将分隔符替换为 '\0',并返回找到的第一个分割部分,同时保存分割结束的位置到静态指针中。
  2. 后续调用

    token = strtok(NULL, delim);
    
    • 参数 NULL 告诉 strtok 使用保存的静态指针,从上次分割结束的位置继续分割。
    • 每次分割后,strtok 会更新静态指针的位置。

示例分析

#include <stdio.h>
#include <string.h>int main() {char str[] = "C,programming,is,fun";const char *delim = ",";char *token;// 初次调用 strtoktoken = strtok(str, delim);printf("First token: %s\n", token); // 输出 "C"// 后续调用 strtoktoken = strtok(NULL, delim);printf("Second token: %s\n", token); // 输出 "programming"token = strtok(NULL, delim);printf("Third token: %s\n", token); // 输出 "is"token = strtok(NULL, delim);printf("Fourth token: %s\n", token); // 输出 "fun"token = strtok(NULL, delim);printf("Final token: %s\n", token); // 输出 "(null)",分割完成return 0;
}

输出

First token: C
Second token: programming
Third token: is
Fourth token: fun
Final token: (null)

内部指针变化

  1. 初次调用:
    • str"C,programming,is,fun"
    • 静态指针保存分割后的位置 "programming,is,fun"
  2. 第二次调用:
    • 使用静态指针继续分割。
    • 静态指针更新为 "is,fun"
  3. 第三次调用:
    • 静态指针更新为 "fun"
  4. 第四次调用:
    • 静态指针更新为 NULL

静态指针的局限性

1. 线程不安全

strtok 的静态指针是全局共享的,多个线程同时调用 strtok 会导致状态混乱。

解决方案:使用线程安全的 strtok_r 函数,它将状态保存到用户提供的指针(而非静态变量)中。

2. 不能同时分割多个字符串

因为 strtok 的静态指针只能记录一个字符串的分割状态。如果需要同时分割多个字符串,应使用其他方法(如 strtok_r 或自定义逻辑)。


总结

  • strtok 用于字符串分割,但会修改原字符串,并且线程不安全。
  • 多线程环境下,推荐使用 strtok_r
  • 分割的字符串存储在原字符串中,指针返回的是分割后的部分,原字符串会被破坏。

相关文章:

C语言strtok()函数用法详解!

strtok 是 C 标准库中的字符串分割函数&#xff0c;用于将一个字符串拆分成多个部分&#xff08;token&#xff09;&#xff0c;以某些字符&#xff08;称为分隔符&#xff09;为界限。 函数原型 char *strtok(char *str, const char *delim);参数&#xff1a; str&#xff1a…...

【docker 拉取镜像超时问题】

问题描述 在centosStream8上安装docker&#xff0c;使用命令sudo docker run hello-world 后出现以下错误&#xff1a; Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Ti…...

模拟手机办卡项目(移动大厅)--结合面向对象、JDBC、MYSQL、dao层模式,使用JAVA控制台实现

目录 1. 项目需求 2. 项目使用的技术 3.项目需求分析 3.1 实体类和接口 4.项目结构 5.业务实现 5.1 登录 5.1.1 实现步骤 5.1.2 原生代码问题 ​编辑 5.1.3 解决方法 1.说明&#xff1a; 2. ResultSetHandler结果集处理 5.1.4 代码 5.1.5 实现后的效果图 登录成功​…...

机器学习—大语言模型:推动AI新时代的引擎

云边有个稻草人-CSDN博客 目录 引言 一、大语言模型的基本原理 1. 什么是大语言模型&#xff1f; 2. Transformer 架构 3. 模型训练 二、大语言模型的应用场景 1. 文本生成 2. 问答系统 3. 编码助手 4. 多语言翻译 三、大语言模型的最新进展 1. GPT-4 2. 开源模型 …...

C++:探索哈希表秘密之哈希桶实现哈希

文章目录 前言一、链地址法概念二、哈希表扩容三、哈希桶插入逻辑四、析构函数五、删除逻辑六、查找七、链地址法代码实现总结 前言 前面我们用开放定址法代码实现了哈希表&#xff1a; C&#xff1a;揭秘哈希&#xff1a;提升查找效率的终极技巧_1 对于开放定址法来说&#…...

具身智能高校实训解决方案——从AI大模型+机器人到通用具身智能

一、 行业背景 在具身智能的发展历程中&#xff0c;AI 大模型的出现成为了关键的推动力量。这些大模型具有海量的参数和强大的语言理解、知识表示能力&#xff0c;能够为机器人的行为决策提供更丰富的信息和更智能的指导。然而&#xff0c;单纯的大模型在面对复杂多变的现实…...

【消息序列】详解(8):探秘物联网中设备广播服务

目录 一、概述 1.1. 定义与特点 1.2. 工作原理 1.3. 应用场景 1.4. 技术优势 二、截断寻呼&#xff08;Truncated Page&#xff09;流程 2.1. 截断寻呼的流程 2.2. 示例代码 2.3. 注意事项 三、无连接外围广播过程 3.1. 设备 A 启动无连接外围设备广播 3.2. 示例代…...

【RL Base】强化学习核心算法:深度Q网络(DQN)算法

&#x1f4e2;本篇文章是博主强化学习&#xff08;RL&#xff09;领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对相关等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅…...

深入浅出 Python 网络爬虫:从零开始构建你的数据采集工具

在大数据时代&#xff0c;网络爬虫作为一种数据采集技术&#xff0c;已经成为开发者和数据分析师不可或缺的工具。Python 凭借其强大的生态和简单易用的语言特点&#xff0c;在爬虫领域大放异彩。本文将带你从零开始&#xff0c;逐步构建一个 Python 网络爬虫&#xff0c;解决实…...

美国发布《联邦风险和授权管理计划 (FedRAMP) 路线图 (2024-2025)》

文章目录 前言一、战略目标实施背景2010年12月&#xff0c;《改革联邦信息技术管理的25点实施计划》2011年2月&#xff0c;《联邦云计算战略》2011年12月&#xff0c;《关于“云计算环境中的信息系统安全授权”的首席信息官备忘录》2022年12月&#xff0c;《FedRAMP 授权法案》…...

Python语法基础(三)

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 我们这篇文章来说一下函数的返回值和匿名函数 函数的返回值 我们先来看下面的这一段函数的定义代码 # 1、返回值的意义 def func1():print(111111111------start)num166print…...

云计算之elastaicsearch logstach kibana面试题

1.ELK是什么? ELK 其实并不是一款软件,而是一整套解决方案,是三个软件产品的首字母缩写 Elasticsearch:负责日志检索和储存 Logstash:负责日志的收集和分析、处理 Kibana:负责日志的可视化 这三款软件都是开源软件,通常是配合使用,而且又先后归于 Elastic.co 公司名下,…...

【已解决】git push需要输入用户名和密码问题

解决方法&#xff1a; 1&#xff09;查看使用的clone方式&#xff1a; git remote -v 2&#xff09;若为HTTPS&#xff0c;删除原clone方式: git remote rm origin 3&#xff09;添加新的clone方式&#xff1a; git remote add origin gitgithub.com:zludon/git_test.git …...

python的字符串处理

需求&#xff1a; 编写一个程序&#xff0c;输入一段英文句子&#xff0c;统计每个单词的长度&#xff0c;并将单词按照长度从短到长排序。 程序逻辑框图 1、用户输入一句英文句子。 2、对输入的句子进行预处理&#xff08;去空格并分割为单词列表&#xff09;。 3、统计每个单…...

【线程】Java多线程代码案例(2)

【线程】Java多线程代码案例&#xff08;2&#xff09; 一、定时器的实现1.1Java标准库定时器1.2 定时器的实现 二、线程池的实现2.1 线程池2.2 Java标准库中的线程池2.3 线程池的实现 一、定时器的实现 1.1Java标准库定时器 import java.util.Timer; import java.util.Timer…...

虚拟机之间复制文件

在防火墙关闭的前提下&#xff0c;您可以通过几种不同的方法将文件从一个虚拟机复制到另一个虚拟机。这里&#xff0c;我们假设您想要从 IP 地址为 192.168.4.5 的虚拟机上的 /tmp 文件夹复制文件到当前虚拟机&#xff08;192.168.4.6&#xff09;的 /tmp 文件夹下。以下是几种…...

如何为 XFS 文件系统的 /dev/centos/root 增加 800G 空间

如何为 XFS 文件系统的 /dev/centos/root 增加 800G 空间 一、前言二、准备工作三、扩展逻辑卷1. 检查现有 LVM 配置2. 扩展物理卷3. 扩展卷组4. 扩展逻辑卷四、调整文件系统大小1. 检查文件系统状态2. 扩展文件系统五、处理可能出现的问题1. 文件系统无法扩展2. 磁盘空间不足3…...

Java算法OJ(11)双指针练习

目录 1.前言 2.正文 2.1存在重复数字 2.1.1题目 2.1.2解法一代码 解析&#xff1a; 2.1.3解法二代码 解析&#xff1a; 2.2存在重复数字plus 2.2.1题目 2.2.2代码 2.2.3解析 3.小结 1.前言 哈喽大家好吖&#xff0c;今天来给大家分享双指针算法的相关练习&…...

44.扫雷第二部分、放置随机的雷,扫雷,炸死或成功 C语言

按照教程打完了。好几个bug都是自己打出来的。比如统计周围8个格子时&#xff0c;有一个各自加号填成了减号。我还以为平移了&#xff0c;一会显示是0一会显示是2。结果单纯的打错了。debug的时候断点放在scanf后面会顺畅一些。中间多放一些变量名方便监视。以及mine要多显示&a…...

大语言模型LLM的微调代码详解

代码的摘要说明 一、整体功能概述 这段 Python 代码主要实现了基于 Hugging Face Transformers 库对预训练语言模型&#xff08;具体为 TAIDE-LX-7B-Chat 模型&#xff09;进行微调&#xff08;Fine-tuning&#xff09;的功能&#xff0c;使其能更好地应用于生成唐诗相关内容的…...

AlphaFold 3终极指南:掌握Jackhmmer与HMMER提升蛋白质结构预测精度

AlphaFold 3终极指南&#xff1a;掌握Jackhmmer与HMMER提升蛋白质结构预测精度 【免费下载链接】alphafold3 AlphaFold 3 inference pipeline. 项目地址: https://gitcode.com/gh_mirrors/alp/alphafold3 你是否在蛋白质结构预测项目中遇到MSA生成效率低下的瓶颈&#x…...

基于XGBoost与SHAP的分子气味预测:从特征工程到可解释性分析

1. 项目概述与核心价值在香水设计、食品风味工业乃至环境监测领域&#xff0c;一个核心且持久的挑战是&#xff1a;如何从分子的化学结构出发&#xff0c;准确预测其气味&#xff1f;这不仅仅是化学家或调香师的直觉游戏&#xff0c;更是一个复杂的、高维度的模式识别问题。传统…...

Sentinel-3B OLCI 3 级全球分箱地球观测降分辨率(ERR)叶绿素(CHL)数据,版本 2022.0

Sentinel-3B OLCI Level-3 Global Binned Earth-observation Reduced Resolution (ERR) Chlorophyll (CHL) Data, version 2022.0 简介 叶绿素 a 数据集提供全球网格化的表层叶绿素 a 浓度&#xff08;浮游植物生物量的替代指标&#xff09;合成数据。CHL 支持时间序列和气候…...

从社交关系到分子结构:图解GCN(图卷积网络)到底在‘看’什么?

从社交关系到分子结构&#xff1a;图解GCN&#xff08;图卷积网络&#xff09;到底在‘看’什么&#xff1f;想象一下&#xff0c;你刚搬到一个新社区&#xff0c;想快速了解周围的邻居。最直接的方式是什么&#xff1f;不是挨家挨户敲门&#xff0c;而是通过社区活动认识几位关…...

BurpSuite 2025插件开发JDK版本兼容性实战指南

1. 为什么BurpSuite插件开发环境总在JDK版本上翻车&#xff1f;你是不是也经历过&#xff1a;下载好BurpSuite最新版2025.4&#xff0c;兴冲冲打开插件开发文档&#xff0c;照着官方示例写完第一个HelloWorld插件&#xff0c;一编译——java.lang.UnsupportedClassVersionError…...

FT231XQ USB串口桥接板设计解析与实战应用指南

1. 项目概述&#xff1a;从FT232R到FT231XQ的USB串口桥接板演进在嵌入式开发和硬件调试的日常工作中&#xff0c;一个可靠、小巧且功能清晰的USB转串口&#xff08;UART&#xff09;桥接板&#xff08;Breakout Board&#xff0c; 简称BoB&#xff09;几乎是工程师手边的标配工…...

孤舟笔记 互联网常用框架篇二 Dubbo服务请求失败怎么处理?集群容错策略你用过几种

文章目录先说结论Failover&#xff1a;换家店试试Failfast&#xff1a;不行就算了Failsafe&#xff1a;忘了这事Failback&#xff1a;回头再说Forking&#xff1a;同时点几家Broadcast&#xff1a;通知所有人怎么选择回答技巧与点评加分回答面试官点评个人网站分布式系统中&…...

【与我学 ClaudeCode】协作篇 之 Worktree + Task Isolation :目录隔离的并行执行通道

作者&#xff1a;逆境不可逃 技术永无止境 希望我的内容可以帮助到你&#xff01;&#xff01;&#xff01;&#xff01; 大家吼 ! 我是 逆境不可逃 今天给大家带来文章《【与我学 ClaudeCode】协作篇 之 Worktree Task Isolation &#xff1a;目录隔离的并行执行通道》. Le…...

淘宝淘金币自动化脚本终极指南:如何每天节省25分钟实现智能任务管理

淘宝淘金币自动化脚本终极指南&#xff1a;如何每天节省25分钟实现智能任务管理 【免费下载链接】taojinbi 淘宝淘金币自动执行脚本&#xff0c;包含蚂蚁森林收取能量&#xff0c;芭芭农场全任务&#xff0c;解放你的双手 项目地址: https://gitcode.com/gh_mirrors/ta/taoji…...

NPU跑LLM实战指南:KV Cache动态性如何突破硬件限制

NPU跑LLM实战指南:KV Cache动态性如何突破硬件限制 副标题: 从预分配+Attention Mask到三层软件栈,完整解析NPU推理架构 痛点:为什么NPU跑LLM这么难? LLM的生成机制和NPU的硬件特性存在根本冲突: LLM特性 NPU特性 冲突点 逐token生成 固定shape执行 KV Cache动态增长 动…...