c语言strtok函数完美实现

2023-05-16

看到网上好多错误的strtok实现,也不能说错,准确的说是没有完全的实现strtok,现自己写了下,目前还没有找到bug,如果有不对的欢迎指出。

大多数网上的strtok实现的代码跑不过a[]={“abc....123,,,,”},c[]={“.,”},就算跑过了,都是将a[]里的“.,”全部给置‘’了,更支持不了此等循环的调用例如:

char *ret = mystrtok(a, c);

    printf("%s %s ", a, ret);

    printf("%p %p ", a, ret);

    while(ret != NULL)

    {

        ret = mystrtok(NULL, c);

        printf("%s %s ", a, ret);

        printf("%p %p ", a, ret);

    }

 

 

 

以下是代码实现

#include <stdio.h>

#include <string.h>

#include <assert.h>

char *mystrtok(char *str, const char *delim)

{

 assert(delim != NULL);

 static char *str_next = NULL;

//用于记录置“”的后一个地址,准确的说是后一个字节地址,也就是下个字符的地址。一定要用static以免下次调用时被释放掉

 

//此循环的作用,是将str_next记录了置'\0'后一个字符的地址,进行了移位,,,为什么要移位呢,,因为其实strtok其实只将str字符串中有delim字符串中的字符进行了一次置'\0',而不是全部置'\0',例:字符串a[]={“ha,,,,,hihi....ser”},调用三次后,其实此时字符串a应该是“ha'\0',,,,hihi'\0'...ser”的,将数组a全部打印出来a2等于空,a11也等于空,其它字符是不变的,而不是将字符串置为“ha'\0''\0''\0''\0''\0'hihi'\0''\0''\0''\0'ser”,大家可以去打印来看看,所以我们需要将指针str_next指向“下一个字符串”,,例如上面举的a[]的例子,第二次调用strtok时str_next应该指向hihi的h地址

 while(str_next != NULL && *str_next != '\0')

 { 

  int str_num = 0;

  char *delim_k = (char *)delim;

  while(*delim_k != '\0')

  {

   if(*str_next == *delim_k)

   {

    str_num = 1;

    str_next++;

   }

   delim_k++;

  }

  if(str_num == 0)

  {

   break;

  }

 }

//str和str_next是不能同时为null的,其实“str是不能为空的”,但这里是因为strtok第二次开始调用时,传的参数为null,所以说第一次时str不能为null,第二次开始就可以为null,,因为str_next是记录调用后,置'\0'的后一个字符的地址,所以从第二次开始它不可能为null,所以说str和str_next是不能同时为null的,同时为空的情况只有第一次传str的地址进来时就为null,所以要避免此情况发生,当str_next不为空null也就代表它记录了“下一个字符串”的地址将它赋给str。

 if(str == NULL)

 {

  if(str_next == NULL)

  {

   return NULL;

  }

  str = str_next;

 }

//这是大多数人写的主代码,双层循环判断判断两个字符串是否有相同的字符,有就置'\0',如果只写这个,只适合被调用一次或者说只适合隔断符只有有一个,例如str=“192.168.2.1”中间只有一个字符“.”,,但如果多给它加几个字符,大多数人写的代码也就挂了,例如str=“192....168....2....1”时。

 char *str_i = str;

 while(*str_i != '\0')

 {

  char *delim_i = (char *)delim;

  while(*delim_i != '\0')

  {

   if(*str_i == *delim_i)

   {

    *str_i = '\0';

    str_next = str_i + 1; //记录置'\0'的后一个地址,准确的说是后一个字节地址,也就是下个字符的地址。

    return str;

   }

   delim_i++;

  }

  str_i++;

 }

//第一次没有在字符串str中找到和delim字符串中相同的字符,则还返回str,例1.str=“haha”、delim=“i”   此时虽然没有找到但仍要返回str、但如果在次或多次调用则返回null,例2.str=“zhang..san”、delim=“.”   此时虽然第一次能找到“.” ,但在次调用指针就指向字符“s”了,此时就和例1一样了。用static修饰n,防止n被释放。

 static int n = 0;

 n++;

 if(n == 1)

 {

  return str;

 }

 else

 {

  return NULL;

 }

 

}

//主函数试调

int main()

{

 char a[] = "zhan1;.,.san2,..196";

 char b[] = "123,456";

 char c[] = ".,;";

 

 char *ret = strtok(a, c);

 printf("%s %s\n", a, ret);

 printf("%p %p\n", a, ret);

 printf("\n");

 while(ret != NULL)

 {

  ret = strtok(NULL, c);

  printf("%s %s\n", a, ret);

  printf("%p %p\n", a, ret);

 }

 

 for(int i = 0; i < 19; i++)

 { 

  printf("a + %d = %c\n", i, a[i]);

 }

 return 0;

}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c语言strtok函数完美实现 的相关文章

  • debian11 sid

    编辑 etc apt sources list xff0c 增加下面二行 xff1a deb http ftp us debian org debian sid main contrib non free deb src http ftp
  • 单片机学习——定时器/计数器

    单片机必学系列 单片机学习 中断系统 单片机学习 存储器详解 xff08 程序存储器 片内RAM 拓展RAM EEPROM xff09 单片机学习 定时器 计数器 单片机学习 A D转换 更新ing 单片机学习 定时器 计数器 单片机必学系
  • ros bag包转mp4视频

    先在 rosbag2video py 脚本中修改相关配置参数 或者在终端命令改也行 如果使用脚本里的默认参数 则可直接运行 python rosbag2video py 2022 02 02 10 41 38 bag 代码如下 span c
  • 零基础入门Jetson Nano——通过OpenCV调用CSI和USB摄像头

    Jetson Nano学习 摄像头调用 前言一 CSI摄像头的调用1 安装v4l2 utils协助工具2 查看摄像头挂载情况3 查看挂载的摄像头详细参数情况4 检测摄像头能否正常工作5 使用OpenCV调用CSI摄像头方式一 利用Gstre
  • HTML搜索框的制作过程

    1 搜索框的构成 input标签和button标签我的理解应该就类似于行内块元素 xff0c 可以设置宽高 xff0c 但同时又不独占一行placeholder 占位文本 就是输入框一开始默认显示的文本 span class token t
  • Linux

    Linux 文件管理创建目录创建文件复制剪切 重命名删除归档 xff08 解压 压缩 xff09 文件查看帮助文档查看信息文件显示当前工作目录切换目录请屏显示文件内容文件内容搜索文件搜索链接文件搜索命令所在位置 Linux系统查看进程终止进
  • isalpha()库函数

    C C 43 43 isalpha 库函数 isalpha 函数用来检测一个字符是否是字母 xff0c 包括大写字母和小写字母 头文件 xff1a 属于ctype h头文件 xff1b 但也包含在iostream头文件下 语法原型 xff1
  • 计算机网络(谢希仁-第八版)第四章习题全解

    4 01 网络层向上提供的服务有哪两种 xff1f 试比较其优缺点 xff1f 虚电路服务和数据报服务 虚电路 优点 xff1a 1 可以提供可靠的通信服务 2 因为数据是沿着建立的虚电路进行传输的 xff0c 因此分组的首部不需要携带完整
  • Linux下线程池(ThreadPool)

    目录 一 线程池相关概念及其优点 二 线程池的实现 一 线程池相关概念及其优点 线程池一种线程使用模式 xff0c 线程过多会带来这个调度的开销进而影响整体的性能 xff0c 而线程池是提前准备好了线程等待着管理者进行分配任务 1 线程池的
  • Golang协程常见面试题

    协程面试题 交替打印奇数和偶数N个协程打印1到maxVal交替打印字符和数字交替打印字符串三个协程打印ABCChannel练习 交替打印奇数和偶数 下面让我们一起来看看golang当中常见的算法面试题 使用两个goroutine交替打印1
  • JS 几种常见的遍历方式

    JS 几种常见的遍历方式 目录 JS 几种常见的遍历方式for循环for in 循环for of 循环forEach循环map方法参考资料 for循环 普通的写法let arr 61 1 2 3 for let i 61 0 i lt ar
  • mp4 转 jpg 图片

    先在 rosbag2video py 脚本中修改相关配置参数 然后运行脚本 python mp4 2 jpg py 代码如下 span class token keyword import span span class token mod
  • C# WinForm界面设计教程

    WinForm 是 Windows Form 的简称 xff0c 是基于 NET Framework 平台的客户端 xff08 PC软件 xff09 开发技术 xff0c 一般使用 C 编程 C WinForm 编程需要创建 Windows
  • 2021 山东大学软件学院 软件工程应用与实践--YOLOV5项目代码分析——(5)

    2021SC 64 SDUSC detection class Detections detections class for yolov5 inference results def init self imgs pred files n
  • Centos7更改ssh端口报错解决

    Centos7 ssh 端口问题解决 报错如下 xff1a failed to start openssh server daemonssh failed to start openssh server daemon 问题总结 xff1a
  • Python 列表的常见操作

    Python 列表的常见操作 从形式上看 xff0c 列表会将所有元素都放在一对中括号 里面 xff0c 相邻元素之间用逗号 分隔 xff0c 如下所示 xff1a element1 element2 element3 elementn x
  • TortoiseGit的安装教程以及用法

    TortoiseGit的安装教程以及用法 TortoiseGit 是基于 TortoiseSVN 的 Git 版本的 Windows Shell 界面 它是开源的 xff0c 可以完全使用免费软件构建 TortoiseGit 支持你执行常规
  • 在idea中向Maven项目添加插件时出现的“找不到插件”错误解决

    大家用idea在pom xml中添加插件时 xff0c 一开始可能都会遇见添加的插件全报红的时候 现在我们把鼠标移到报红的地方 xff0c 他给了我们一个not found错误 xff0c 也就是找不到插件 那么解决方法也非常简单 xff0
  • 安装Ubuntu双系统

    制作U盘启动盘 1 电脑插入U盘 xff0c 格式化U盘 2 下载解压好安装包 链接 xff1a https pan baidu com s 1my5JrSz QRPwRxIOdU4JJQ 提取码 xff1a 1234 解压完成打开文件夹
  • 纯C+纯手写+手动编译 一个windows 窗体应用(过程记录)

    xff08 纯C 43 纯手写 43 手动编译 xff09 一个Windows 窗体应用 本篇文章仅仅是作者的一个类似笔记一样的东西 xff0c 作为记录 所以请勿出现如下不友善评论 啊 xff0c 这不是某某IDE直接就可以生成的吗 搞这

随机推荐