搜索
首页后端开发C#.Net教程strtok函数的用法是什么

strtok函数的用法是什么

Oct 28, 2020 am 09:48 AM
strtok函数

strtok函数的用法:1、作用于字符串s,以delim中的字符为分界符,将s切分成一个个子串;2、如果s为空值NULL,则函数保存的指针【SAVE_PTR】在下一次调用中将作为起始位置。

strtok函数的用法是什么

相关免费推荐:编程视频课程

strtok函数的用法:

一、函数的简介

         函数原型:char *strtok(char *s, char *delim)

         功能:作用于字符串s,以delim中的字符为分界符,将s切分成一个个子串;如果,s为空值NULL,则函数保存的指针SAVE_PTR在下一次调用中将作为起始位置。

         返回值:分隔符匹配到的第一个子串

二、主要内容

        1、函数的作用是分解字符串,所谓分解,即没有生成新串,只是在s所指向的内容首次出现分界符的位置,将分界符修改成了'/0’,故第一次用strtok()返回第一个子串

         2、第一次提取子串完毕之后,继续对源字符串s进行提取,应在其后(第二次,第三次。。。第n次)的调用中将strtok的第一个参数赋为空值NULL(表示函数继续从上   一次调用隐式保存的位置,继续分解字符串;对于前一次次调用来说,第一次调用结束前用一个this指针指向了分界符的下一位

         3、当this指针指向“\0” 时,即没有被分割的子串了,此时则返回NULL

         4、可以把delim理解为分隔符的集合delim中的字符均可以作为分隔符。

         5、strtok在调用的时候,如果起始位置即为分隔符,则忽略了起始位置开始的分隔符


三、使用strtok需要注意的有以下几点:

1.函数的作用是分解字符串,所谓分解,即没有生成新串,只是在s所指向的内容上做了些手脚而已。因此,源字符串s发生了变化!

设源字符串s为 char buffer[INFO_MAX_SZ]=",Fred male 25,John male 62,Anna female 16";  过滤字符串delim为 char *delim = " ",即空格为分界符。

 5fc2ead8ed6e5319671c5f17bca2492.png

上图的代码会产生这样的结果:

d6d435e4c9acec5c9ee8fb3dbf8daf6.png

首先,buffer发生了变化。如果此时打印buffer的值,会显示“,Fred”,而后面" male 25…16”不翼而飞了。实际上,strtok函数根据delim中的分界符,找到其首次出现的位置,即Fred后面那个空格(buffer[5]),将其修改成了'/0’。其余位置不变。这就很好解释为什么打印buffer的值只能出现“,Fred”,而非buffer中的全部内容了。因此,使用strtok时一定要慎重,以防止源字符串被修改。 

理解了buffer的变化,就很好解释函数的返回值了。返回值buf为分界符之前的子串(其实这个说法并不确切,详见"3”中对于返回值的详细说明)。注意,由变量的地址可知,buf依然指向源字符串。

64513f809d395693aa82d8b5c7f3cb4.png

分界符delim没有发生变化,就不再截图了。

 

2.若要在第一次提取子串完毕之后,继续对源字符串s进行提取,应在其后(第二次,第三次。。。第n次)的调用中将strtok的第一个参数赋为空值NULL。

8b6cdef3d01432f9e3ecd5f47f65ecd.png

第一次调用的结果如前文所述,提取出了",Fred”。我们还想继续以空格为分界,提取出后面的"male”等。由上图可以看到,第一次之后的调用我们都给strtok的第一个参数传递了空值NULL(表示函数继续从上一次调用隐式保存的位置,继续分解字符串;对于上述的第二次调用来说,第一次调用结束前用一个this指针指向了分界符的下一位,即'm’所在的位置),这样可依次提取出

fbe7f1ecde9c54eb69115199d8b2e8b.pnga22f976065ff3e7643db39249e71283.png 。。。。以此类推。。。。。

至于为什么要赋空值,要么你就记住结论,要么去查strtok的源代码。本文的最后会有一些介绍。

当然也有部分爱钻牛角尖的人,非不按套路出牌,要看看不赋空值继续赋值为buffer会有什么结果。其实,答案想也能想的到。再一次传递buffer,相当于还从字符串的开头查找分界符delim,而且此时buffer已经被修改(可见的部分只剩下",Fred”),因此,其结果必然是找不到分界符delim。

 

3.关于函数返回值的探讨

由"1”中所述,在提取到子串的情况下,strtok的返回值(假设返回值赋给了指针buf)是提取出的子串的指针。这个指针指向的是子串在源字符串中的起始位置。子串末尾的下一个字符在提取前为分隔符,提取后被修改成了'/0’。因此,若打印buf的值,可以成功的输出子串的内容。

在没有提取到子串的情况下,函数会返回什么值呢?

4ff4ee3314fdf15017688e23450b751.png

由上图可以看到buffer中并不包含分界符delim。调用strtok后buf的值为

8c0afe05443b8da09df557257c94d94.png

因为没有找到,源字符串buffer没有发生改变,buf指向源字符串的首地址,打印输出的值为整个字符串的完整值。

什么时候函数的返回值为空值NULL呢?

百度百科上说,“当没有被分割的串时则返回NULL。”这是一个很模棱两可的说法。如果想要确切的了解清楚这个问题,可能需要看一下strtok的实现原理。这里先以实验说明。

e37f40f54d85f992f4bd25bef712570.png

第一次调用strtok,毫无疑问,buf指向",Fred”。

第二次调用strtok,由于第一个参数为NULL,表示函数继续以上次调用所保存的this指针的位置开始分解,即对"male 25”分解。分解完毕后,buf指向"male”。

第三次调用strtok,参数继续设定为NULL,此时即对第二次保存的this指针的位置开始分解,即对"25”分解。因为无法找到包含分隔符delim的子串,所以buf指向"25”。

2c325eb6fa86c1cd6c804b35b2669bb.png

第四次调用,参数仍为NULL,此时第三次调用保存的this指针已指向字符串的末尾'/0’,已无法再进行分解。因此函数返回NULL,这也就是百度百科中所提到的“当没有被分割的串时函数返回NULL。”

db5252ad4fc5a8c1ea94bd541a94da2.png

 

4.参数 分隔符delim的探讨(delim是分隔符的集合)

很多人在使用strtok的时候,都想当然的以为函数在分割字符串时完整匹配分隔符delim,比如delim=”ab”,则对于"acdab”这个字符串,函数提取出的是"acd”。至少我在第一次使用的时候也是这么认为的。其实我们都错了,我是在看函数的源代码时才发现这个问题的,且看下面的例子。

068cdb90ad4024883f3519457b3cab5.png

源字符串为buffer,分隔符delim为 逗号和空格,按照一般的想法我们会以为调用函数后,buf的值为"Fred,male,25”,结果是这样么?

033b30edc6b8ada9f9cad3304ea38ea.png

第一次调用之后的结果竟然是"Fred”,而非我们所想的结果。这是为什么呢?

我们回到GNU C Library中对strtok的功能定义:“Parse S into tokens separated by characters in DELIM”。也就是说包含在delim中的字符均可以作为分隔符,而非严格匹配。可以把delim理解为分隔符的集合。这一点是非常重要的~

当然,我们在分解字符串的时候,很少使用多个分隔符。这也导致,很多人在写例子的时候只讨论了一个分隔符的情况。有更多的人在看例子的时候也就错误的认识了delim的作用。

5.待分解的字符串,首字符就为分隔符

首字符为分隔符不能算作一个很特殊的情况。按照常规的分解思路也能正确分解字符串。

我想说明的是,strtok对于这种情况采用了比常规处理更快的方式。

241af81bb6e3701f83ae80b7f1b7639.png

如上图例子所示。仅用一次调用就可以得到以逗号分隔的字符串"Fred male 25”,而F前面的','被忽略了。由此可见,strtok在调用的时候忽略了起始位置开始的分隔符。这一点,可以从strtok的源代码得到证实。

6.不能向第一个参数传递字符串常量!

本文中所举的例子都将源字符串保存为字符串数组变量。若你将源字符串定义成字符串常量,可想而知,程序会因为strtok函数试图修改源字符串的值,而抛出异常。

da4ea861caf33ceaaf36b89e2012c8f.png

以上是strtok函数的用法是什么的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
.NET生态系统:C#的角色和超越.NET生态系统:C#的角色和超越May 03, 2025 am 12:04 AM

C#在.NET生态系统中扮演核心角色,是开发者的首选语言。1)C#提供高效、易用的编程方式,结合C、C 和Java的优点。2)通过.NET运行时(CLR)执行,确保跨平台高效运行。3)C#支持从基本到高级的用法,如LINQ和异步编程。4)优化和最佳实践包括使用StringBuilder和异步编程,提高性能和可维护性。

C#作为.NET语言:生态系统的基础C#作为.NET语言:生态系统的基础May 02, 2025 am 12:01 AM

C#是微软在2000年发布的编程语言,旨在结合C 的强大功能和Java的简洁性。1.C#是一种类型安全、面向对象的编程语言,支持封装、继承和多态。2.C#的编译过程将代码转化为中间语言(IL),然后在.NET运行时环境(CLR)中即时编译成机器码执行。3.C#的基本用法包括变量声明、控制流和函数定义,而高级用法涵盖异步编程、LINQ和委托等。4.常见错误包括类型不匹配和空引用异常,可通过调试器、异常处理和日志记录来调试。5.性能优化建议包括使用LINQ、异步编程和提高代码可读性。

c#vs. .net:澄清关键差异和相似之处c#vs. .net:澄清关键差异和相似之处May 01, 2025 am 12:12 AM

C#是一种编程语言,而.NET是一个软件框架。1.C#由微软开发,适用于多平台开发。2..NET提供类库和运行时环境,支持多语言。两者协同工作,构建现代应用。

超越炒作:评估C#.NET的当前作用超越炒作:评估C#.NET的当前作用Apr 30, 2025 am 12:06 AM

C#.NET是一个强大的开发平台,结合了C#语言和.NET框架的优势。1)它广泛应用于企业应用、Web开发、游戏开发和移动应用开发。2)C#代码编译成中间语言后由.NET运行时环境执行,支持垃圾回收、类型安全和LINQ查询。3)使用示例包括基本控制台输出和高级LINQ查询。4)常见错误如空引用和类型转换错误可以通过调试器和日志记录解决。5)性能优化建议包括异步编程和优化LINQ查询。6)尽管面临竞争,C#.NET通过不断创新保持其重要地位。

C#.NET的未来:趋势和机遇C#.NET的未来:趋势和机遇Apr 29, 2025 am 12:02 AM

C#.NET的未来趋势主要集中在云计算、微服务、AI和机器学习集成以及跨平台开发三个方面。1)云计算和微服务:C#.NET通过Azure平台优化云环境表现,支持构建高效微服务架构。2)AI和机器学习集成:借助ML.NET库,C#开发者可在应用中嵌入机器学习模型,推动智能化应用发展。3)跨平台开发:通过.NETCore和.NET5 ,C#应用可在Windows、Linux和macOS上运行,扩展部署范围。

C#.NET开发今天:趋势和最佳实践C#.NET开发今天:趋势和最佳实践Apr 28, 2025 am 12:25 AM

C#.NET开发的最新动态和最佳实践包括:1.异步编程提高应用响应性,使用async和await关键字简化非阻塞代码;2.LINQ提供强大查询功能,通过延迟执行和表达式树高效操作数据;3.性能优化建议包括使用异步编程、优化LINQ查询、合理管理内存、提升代码可读性和维护性、以及编写单元测试。

C#.NET:使用.NET生态系统构建应用程序C#.NET:使用.NET生态系统构建应用程序Apr 27, 2025 am 12:12 AM

如何利用.NET构建应用?使用.NET构建应用可以通过以下步骤实现:1)了解.NET基础知识,包括C#语言和跨平台开发支持;2)学习核心概念,如.NET生态系统的组件和工作原理;3)掌握基本和高级用法,从简单控制台应用到复杂的WebAPI和数据库操作;4)熟悉常见错误与调试技巧,如配置和数据库连接问题;5)应用性能优化与最佳实践,如异步编程和缓存。

C#作为多功能.NET语言:应用程序和示例C#作为多功能.NET语言:应用程序和示例Apr 26, 2025 am 12:26 AM

C#在企业级应用、游戏开发、移动应用和Web开发中均有广泛应用。1)在企业级应用中,C#常用于ASP.NETCore开发WebAPI。2)在游戏开发中,C#与Unity引擎结合,实现角色控制等功能。3)C#支持多态性和异步编程,提高代码灵活性和应用性能。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),