【 C 】高级字符串查找之 strspn 和 strcspn 的思考
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
再给出一个测试例子:
#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
【 C 】高级字符串查找之 strspn 和 strcspn 的思考的更多相关文章
- 【 C 】高级字符串查找之查找标记(token)函数 strtok介绍
我的csdn博客 一个字符串常常包含几个单独的部分,它们彼此被分隔开来.每次为了处理这些部分,你首先必须把它们从字符串中抽取出来. 这个任务有#include<string.h>中的str ...
- C/C++字符串查找函数
C/C++ string库(string.h)提供了几个字符串查找函数,如下: memchr 在指定内存里定位给定字符 strchr 在指定字符串里定位给定字符 strcspn 返回在字符串str1里 ...
- C/C++字符串查找函数 <转>
C/C++ string库(string.h)提供了几个字符串查找函数,如下: memchr 在指定内存里定位给定字符 strchr 在指定字符串里定位给定字符 strcspn 返回在字符串str1里 ...
- Rabin-Karp指纹字符串查找算法
首先计算模式字符串的散列函数, 如果找到一个和模式字符串散列值相同的子字符串, 那么继续验证两者是否匹配. 这个过程等价于将模式保存在一个散列表中, 然后在文本中的所有子字符串查找. 但不需要为散列表 ...
- 自己动手写文件查找,字符串查找,查询jar包等工具
文件查找——搜索当前目录下的文件 知道大概的文件名称,使用 findf FileName findf.py import argparse, re, os from os.path import jo ...
- 关于字符串查找 charindex ,Patindex 还有一个like
字符串查找.在模糊朝找的情况下,其实3者的效率是差不多的.都需要一个一个取出来然后扫一遍╮(╯_╰)╭.然而用法还是会有一点儿的区别 1 charindex (查找的字符串,字符串表达式[,开始查找的 ...
- python 字符串查找
python 字符串查找有4个方法,1 find,2 index方法,3 rfind方法,4 rindex方法. 1 find()方法: )##从下标1开始,查找在字符串里第一个出现的子串:返回结果3 ...
- Sunday算法(字符串查找、匹配)
字符串查找算法中,最著名的两个是KMP算法(Knuth-Morris-Pratt)和BM算法(Boyer-Moore).两个算法在最坏情况下均具有线性的查找时间.但是在实用上,KMP算法并不比最简单的 ...
- lintcode:strStr 字符串查找
题目: 字符串查找 字符串查找(又称查找子字符串),是字符串操作中一个很有用的函数.你的任务是实现这个函数. 对于一个给定的 source 字符串和一个 target 字符串,你应该在 source ...
随机推荐
- Python学习---装饰器的学习1210
装饰器的基础 学习前提: 作用域 + 函数的理解 + 闭包 [学习,理解] 代码编写原则: 对修改开放对扩展开放 装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的前 ...
- 6 Dockerfile指令详解 && ENTRYPOINT 指令
ENTRYPOINT 的格式和 RUN 指令格式一样,分为 exec 格式和 shell 格式. ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数. ENTRYPOINT 在 ...
- (转)如何解决VC中的警告warning C4251 needs to have dll-interface
这通常是由于以数据成员方式在DLL导出类中使用了模板类造成的.比如: #include <iostream> #include <vector> using namespace ...
- codeforces 414D Mashmokh and Water Tanks
codeforces 414D Mashmokh and Water Tanks 题意 题解 \(a_i\):第 \(i\) 层的结点个数. \(b_i\):第 \(i\) 层初始有水的结点个数. 如 ...
- U-Mail:邮件营销如何大量获取并筛选有效地址
工欲善其事必先利其器,在所有的邮件推广中,最基础的工作就是收集到足够多的有效邮箱地址,俗话说韩信将兵多多益善,邮箱地址越多,也就意味着潜在的转化为消费者的数量众多,但是如果大量滥竽充数的地址被搜罗进来 ...
- Appfuse搭建过程(下源代码不须要maven,lib直接就在项目里(否则痛苦死!))
什么是Appfuse:AppFuse是一个集成了众多当前最流行开源框架与工具(包含Hibernate.ibatis.Struts.Spring.DBUnit.Maven.Log4J.Struts Me ...
- Linux环境下GNU, GCC, G++编译器
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u012823258/article/details/36890125 一.GNU GNU是" ...
- 解决 php7下 igbinary_unserialize_ref: invalid reference 的bug
最近组内升级了PHP7,某个接口偶发502,看了下php的错误日志如下: igbinary_unserialize_ref: invalid reference >= Memcached::ge ...
- [Python 多线程] multiprocessing、多进程、工作进程池 (十四)
由于Python的GIL限制,多线程未必是CPU密集型程序的好的选择. 多进程可以完全独立的进程环境中运行程序,可以充分地利用多处理器. 但是进程本身的隔离性带来的数据不共享也是一个问题.而且线程比进 ...
- jquery全选 反选
//全选 反选 $('#chkAll').on('click',function(){ $('input.chkbox').prop('checked',$(this).prop('checked') ...