【 C 】高级字符串查找之 strspn 和 strcspn 的思考

版权声明:本博客内容来自于个人学习过程中的总结,参考了互联网以及书本、论文等上的内容,仅供学习交流使用,如有侵权,请联系我会重写!转载请注明地址! https://blog.csdn.net/Reborn_Lee/article/details/82562195

strspn 这个库函数是真的很难理解,看了很多中文描述,反正都是不知所云,给出一系列的例子,结果也是让我瞠目结舌,荒唐、荒谬、荒诞!

特此记录理解过程,最后竟然是百度百科让我明白了这个库函数的意思。

中文的描述真的是太困难了,想用一两句话去说清楚往往不知所云。百度百科上最后给出了这个函数的定义,也就是这个函数是如何实现的,看了几遍才恍然大悟!

因此我也按照这个理解的顺序给出解释(没有耐心读的,不要往下看了,用心的东西往往需要花时间体会!),先给出函数的定义:

int strspn(const char *s,const char *accept)
{
    const char *p;
    const char *a;
    int count = 0;
    for(p = s; *p != '\0'; ++p)
    {
        for (a = accept; *a != '\0'; ++a)
        {
            if (*p == *a)
            {
                ++count;
                break;
            }
        }   //里面的for循环到此为止
        if (*a == '\0')
        {
            return count;
        }

    }   //外面的for循环到此为止
    
    return count;
}

可以这么说,如果你看懂了这个函数定义,难道还不能理解这个函数?

比任何的中文解释更清晰!

那关键是你能看懂这个函数,如果看不懂那就回去再补补基础。

声明:下面这段中文解释如果看不懂,那就自己理解上面的程序,别看了,有些东西只可意会不可言传!

这里为了方便看,对上面函数的定义的要点提出来几点:

关键的是for循环语句的嵌套,内部for函数:

for (a = accept; *a != '\0'; ++a)
        {
            if (*p == *a)
            {
                ++count;
                break;
            }
        }   //里面的for循环到此为止

什么意思呢?就是将accept这个字符数组中的所有字符与目的字符数组 s 中的字符比较,如果相等,则计数器加1,那比较到什么时候结束呢?

比较到accept中的所有字符没有一个与s中字符相等,这时执行内层for循环后面的一条语句:

 if (*a == '\0')
        {
            return count;
        }

这不就是直接返回一个值,就是至此为止的计数值。


当你使用这个函数的使用,当然不需要自己定义,因为这是库函数中定义的,所以,你只需要源程序开头带上#include<string.h>这个头文件即可!

下面举几个例子,看看测试结果:

这是第一个测试的例子:

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

int main () {
   int len;
   const char str1[] = "25,142,330,Smith,J,239-4123";
   const char str2[] = ",0123456789";

   len = strspn(str1, str2);

   printf("Length of initial segment matching %d\n", len );
   
   return(0);
}

结果为:

在这个地方,发现了一个神器,在线写程序并编译的地址:Online C Compiler

http://tpcg.io/luVeGa

再给出一个测试例子:

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

int main () {
   int len;
   const char str1[] = "25,142,330,Smith,J,239-4123";
   const char str2[] = "0123456789";

   len = strspn(str1, str2);

   printf("Length of initial segment matching %d\n", len );
   
   return(0);
}


对了,还有一个于此互补的函数 strcspn,它的作用与上面的函数互补,为了说明清楚,我们给出两个函数的函数原型,便于讨论:

size_t strspn( char const *str, char const *group );

size_t strcspn( char const *str, char const *group );

group字符串指定一个或多个字符。strspn返回str起始部分匹配 group 中任意字符的字符数。这只是一个不太清晰的总结,具体看上面的内容。

strcspn函数和strspn函数正好相反,它对str字符串起始部分中不与group 中任何字符匹配的字符进行计数。 strcspn 这个名字中字母c来源于一组字符求补这个概念,也就是把这些字符换成原先并不存在的字符。

上面这一小段来自于《C与指针》,仅供参考,我也不太明白它在说什么?

举几个例子说明一下吧:

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

int main () {
   int len;
   const char str1[] = ",142,330,Smith,J,239-4123";
   const char str2[] = "0123456789";

   len = strcspn(str1, str2);

   printf("Length of initial segment matching %d\n", len );
   
   return(0);
}

str2字符数组中每一个字符都不与str1字符数组中的第一个字符相等,故计数加1,然后str2中有字符与str1第2个字符匹配的了,说了函数直接返回结果为1.

为了与之对比,我在举一个例子:

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

int main () {
   int len;
   const char str1[] = ",,,Smith,J,239-4123";
   const char str2[] = "0123456789";

   len = strcspn(str1, str2);

   printf("Length of initial segment matching %d\n", len );
   
   return(0);
}


这里根据我的想法,我想给出strcspn的大致定义,应该是这样的:


int strcspn(const char *s,const char *accept)
{
    const char *p;
    const char *a;
    int count = 0;
    for(p = s; *p != '\0'; ++p)
    {
        for (a = accept; *a != '\0'; ++a)
        {
            if (*p == *a)
            {
                return count;
            }
            
        }   //里面的for循环到此为止
        if (*a == '\0')
        {
            ++ count;
        }

    }   //外面的for循环到此为止
    
    return count;
}

不信的话,下面我来测试下它的功能:

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

int main () {
   int len;
   const char str1[] = ",,,Smith,J,239-4123";
   const char str2[] = "0123456789";
   //函数原型
   int my_strcspn(const char *s,const char *accept);

   len = my_strcspn(str1, str2);

   printf("Length of initial segment matching %d\n", len );

   return(0);
}

int my_strcspn(const char *s,const char *accept)
{
    const char *p;
    const char *a;
    int count = 0;
    for(p = s; *p != '\0'; ++p)
    {
        for (a = accept; *a != '\0'; ++a)
        {
            if (*p == *a)
            {
                return count;
            }

        }   //里面的for循环到此为止
        if (*a == '\0')
        {
            ++ count;
        }

    }   //外面的for循环到此为止

    return count;
}

运行得到:

运行示意

可见,结果符合预期!

就到这里吧,最后给出几个不错的网址:

https://baike.baidu.com/item/strspn

https://www.tutorialspoint.com/c_standard_library/c_function_strspn.htm

猜你喜欢

转载自blog.csdn.net/Reborn_Lee/article/details/82562195