字符串函数番外篇

通常看到strrchr这个函数,人们很自然的想问库里面有没有strrstr这个函数呢???

答案是:没有。

但是我们可以自己实现一个strrstr函数,它的功能是查找最后一次出现的子字符串,如果找打则返回这个地址,如果没找到则返回空地址。

实现方案:对于这个函数有两种实现方式。

第一种是从后向前找,第一次找到就返回这个地址。

第二种是从前向后找,用一个标签记录第一次找到的位置,然后当第二次找到时再更新这个标签,最后标签里面保存的地址就是我们要找的地址。

从后向前找:

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

char *my_strrstr(const char *dst, const char *src)
{
    assert(dst );                      //对字符串进行断言,判断是否为空
    assert(src );
    const char *pdst = dst;         
    const char *psrc = src;
    char *tmp = NULL ;               
    while (*pdst)                          //因为要从后向前找,则首先让pdst指向‘\0‘
    {
       pdst++;
     }
     
    while (pdst >= dst )                     //当pdst大于dst则表明dst这个字符串还没有找完
    {
        if (tmp=(char *)strstr(pdst, psrc = src))  //使用strstr帮助寻找,找到保存到tmp
        return tmp;
        
        pdst--;
     }
     
     return NULL ;
}

int main()
{
    char arr[30];
    char arr1[20];
    scanf( "%s%s", arr, arr1);
    char *ret=my_strrstr(arr, arr1);
    printf( "%#p\n", ret);
    system( "pause");
    return 0;
}

//当字符串很大时,效率很高

从前向后找:

char *my_strrstr(const char *dst, const char *src)
{
      assert(dst );
      assert(src );
      const char *pdst = dst;
      const char *psrc = src;
      char *right= NULL ;
      while (*dst )
      {
            while (*pdst == *psrc)
            {
                if (*pdst== ‘\0‘ )               //如果pdst指向‘\0‘则表明目标数组已经找完
                     return right=(char *)dst;
                else
                {
                    pdst++;
                    psrc++;
                 }
             }
             
             if (*psrc == ‘\0‘ )      //src已经则dst中出现,将这个地址保存起来
                right = (char *)dst ;
                
             pdst = ++ dst;
             psrc = src;
        }
        
       return right;
}

int main()
{
     char arr1[50] = { 0 };
     char arr2[40] = { 0 };
     char *place = NULL ;
     scanf( "%s%s",arr1, arr2);
     place = my_strrstr(arr1, arr2);
     printf( "%#p\n",place);
     system( "pause");
     return 0;
}

//当目标字符串很大时,效率特别低

strtok:

功能: 可以将一个字符串按照分隔符分开读取

原型: char * strtok(char *str,const char *sep);

str是要读取的字符串,这个字符串里面包含了若干sep中的字符。sep指向分隔符字符串。strtok找到str中下一个标记,并用‘\0‘替换。

用法:

例:arr[]="[email protected]#ef$gh#"; sep[]="@#$".

将str按照sep中出现的分隔符分隔开来。如果参数arr非空,则strtok将找到第一个标记,将它赋成‘\0‘,并保存它的下一个位置。

第一次调用strtok(arr,sep);返回首地址,保存c的地址。

第二次调用strtok(NULL,sep);str参数为NULL,则strtok从c的位置寻找下一个分隔符。也就是找到#后将#换成‘\0‘并返回c的地址。

此后再调用strtok和第二次类似:如果str参数为NULL,则strtok就在同一个字符串中从上次保存的位置寻找下一个分隔符。

strtok实现:

char *my_strtok(char *dst, char const * sep)
{
     assert(dst );               //断言字符串是否为空
     assert(sep );
     static char *pdst=NULL;    //声明一个静态局部变量
     char *origin = NULL ;    
     if (dst )
       pdst = dst;
     origin = pdst;                  //记录起始位置
     
     while( !strchr(sep , *pdst)||*pdst)      //寻找分隔符,当遇到‘\0‘程序结束
     {
         pdst++;
      }
      
      if (*pdst)                   //如果找到分隔符
           *pdst++ = ‘\0‘;               //将分隔符换成‘\0‘
      return origin;              
}
int main()
{
     char *ret = NULL ;
     char arr[20];
     char *arr1="@#$" ;
     scanf( "%s", arr);
     for (ret = strtok(arr, arr1); ret != NULL; ret = strtok( NULL, arr1))
          printf( "%s\n", ret);
      system( "pause");
      return 0;
}
时间: 2024-10-27 07:54:41

字符串函数番外篇的相关文章

编程珠玑番外篇

1.Plan 9 的八卦 在 Windows 下喜欢用 FTP 的同学抱怨 Linux 下面没有如 LeapFTP 那样的方便的工具. 在苹果下面用惯了 Cyberduck 的同学可能也会抱怨 Linux 下面使用 FTP 和 SFTP 是一件麻烦的事情. 其实一点都不麻烦, 因为在 LINUX 系统上压根就不需要用 FTP. 为什么呢? 因为一行简单的配置之后, 你就可以像使用本机文件一样使用远程的任何文件. 无论是想编辑, 查看还是删除重命名, 都和本机文件一样的用. 这么神奇的功能到底如何

[uboot] (番外篇)uboot 驱动模型(转)重要

[uboot] uboot流程系列:[project X] tiny210(s5pv210)上电启动流程(BL0-BL2)[project X] tiny210(s5pv210)从存储设备加载代码到DDR[uboot] (第一章)uboot流程——概述[uboot] (第二章)uboot流程——uboot-spl编译流程[uboot] (第三章)uboot流程——uboot-spl代码流程[uboot] (第四章)uboot流程——uboot编译流程[uboot] (第五章)uboot流程——u

【喵&quot;的Android之路】【番外篇】有关于null的一些知识点

[喵"的Android之路][番外篇]有关于null的一些知识点 1.首先,到底什么是null? null是Java中的一个关键字,用于表示一个空对象引用,但其本身并不是任何类型也不是属于任何对象.因此,下面的做法是错误的: int a = null; 但: Object obj = null; 是可以的,因为null表示Object类型的一个空对象引用,符合其用意. [注1]引用类型使用null声明对象变量后,无法使用该变量访问对象的成员.例如上述obj对象如果使用obj.toString()

可视化(番外篇)

本篇主要介绍如何在SWT下构建一个应用,如何安装SWT Designer并破解已进行SWT的可视化编程,Display以及Shell为何物.有何用,SWT中的常用组件.面板容器以及事件模型等. 1.可视化环境搭建(SWT Designer): (1).首先下载SWT Designer插件包SWT Designer 6.9.5 for Eclipse.rar: (2).将解压好的插件包extplugins\swt\eclipse下的features和plugins导入Myeclipse的dropi

Linux入门之内核管理番外篇(4)udev入门(1)

Linux入门之内核管理番外篇(4)udev入门(1) 前言 在上篇中的内核模块管理讲解中,最后或多或少会留下一些疑问,那么这些疑问就是内核模块的参数是怎么和对应的硬件所匹配上的,而硬件又是怎么被内核识别,并且一个个都映射成实际存在的文件,而这些文件之间的关系及作用.当然在最后了解到,这些硬件设备的探测信息是通过一个叫udev的工具来实现的,通过udev中配置的规则可以很有效的识别每一个硬件,并配合sysfs文件系统,将每个探测到的硬件信息导入到/sys目录中,那么与/proc目录对与内核系统信

编程珠玑番外篇之番外篇-O 中间语言和虚拟机漫谈(ZZ)

http://blog.youxu.info/2014/05/11/language-and-vm/ 导言 编程语言的发展历史,总的来说,是一个从抽象机器操作逐步进化为抽象人的思维的过程.机器操作和人的思维如一枚硬币的两面,而语言编译器就像是个双面胶,将这两面粘在一起,保证编程语言源程序和机器代码在行为上等价.当然,人本身并不是一个完美的编译器,不能无错的将思维表达为高级语言程序,这种偏差,即Bug.因为编译器的帮助,我们可以脱离机器细节,只关心表达思维和程序行为这一面. 编程语言的发展日新月异

iOS冰与火之歌番外篇 - 在非越狱手机上进行App Hook(转载)

作者简介:郑旻(花名蒸米),阿里巴巴移动安全部门资深安全工程师,香港中文大学移动安全(Android & iOS)方向博士,曾在腾讯.百度以及硅谷的FireEye实习.在博士期间发表了多篇移动安全方向的论文(BlackHat.AsiaCCS等),去过10多个不同的国家做论文演讲. 曾帮助Apple公司修复了多处iOS安全问题,并且Apple在官网表示感谢.同时也是蓝莲花战队和Insight-labs的成员,在业余时间多次参加信息安全竞赛(Defcon.AliCTF.GeekPwn等),并取得优异

可视化(番外篇)——SWT总结

本篇主要介绍如何在SWT下构建一个应用,如何安装SWT Designer并破解已进行SWT的可视化编程,Display以及Shell为何物.有何用,SWT中的常用组件.面板容器以及事件模型等. 1.可视化环境搭建(SWT Designer): (1).首先下载SWT Designer插件包SWT Designer 6.9.5 for Eclipse.rar: (2).将解压好的插件包extplugins\swt\eclipse下的features和plugins导入Myeclipse的dropi

[反汇编练习-番外篇] Delphi专攻

[反汇编练习-番外篇] Delphi专攻 鉴于OD在Delphi反汇编这一块的薄弱,狠狠研究了下当前的手段. 大家常用的反编译除了OD(ollydebug).IDA,还有Delphi用的Dede,C#用的NetReflector,还有几个跟踪易语言的.其实反汇编的利器还有很多,在吾爱云盘中收录了: AS3.Sorcerer.v2.72.CracKed.By.REPT.7z 28-Mar-2014 10:59 5M C32Asm.rar 28-Dec-2013 14:52 1M DJ.Java.D