Night gathers, and now my watch begins.
It shall not end until my death.
I shall take no wife, hold no lands, father no children.
I shall wear no crowns and win no glory.
I shall live and die at my post.
I am the sword in the darkness.
I am the watcher on the walls
.I am the fire that burns against the cold, the light that wakes the sleepers, the shield that guards the realms of men.
I pledge my life and honor to the Night’s Watch, for this night, and all the nights to come.
长夜将至,我从今开始守望,至死方休。
我将不娶妻、不封地、不生子。
我将不戴宝冠,不争荣宠。
我将尽忠职守,生死於斯。
我是黑暗中的利剑,长城中的守卫。
我是抵御寒冷的烈焰,破晓时分的光线,唤醒死者的号角,守护王国的铁卫。
我将生命与荣耀献给守夜人,
今夜如此,夜夜皆然。
– 《权力的游戏》守夜人宣言
最近经常使用到在某个字符串中搜索某个字符串的功能,本来还想着如何去实现,后来发现 C 语言的标准库函数就有提供,借鉴(抄袭 )不香吗?
下面就来一波源码分析。
源码下载地址:The GNU C Library (glibc) 或者 µ C l i b c
首先这个函数的作用是搜索子字符串,如果使用标准库函数,那么就得包含头文件 <string.h>
。
看一下函数原型:
char *strstr(const char *s1, const char *s2);
也就是在 s1
中搜索s2
字符串出现的位置。
返回指针,此指针指向 s1
字符串中的字符第一次出现在 s2
字符串中的位置。如果没有发现匹配,就返回空指针。
下面看一下该函数源码的实现:
char *strstr(const char *s1, const char *s2) //使用const可以保证函数不会修改指针所指向内容
{
int s1_len, s2_len;
s2_len = strlen(s2);
if (!s2_len) //若S2字符串为空,返回空指针
return (char *)s1;
s1_len = strlen(s1);
while (s1_len >= s2_len)
{
s1_len--;
if (!memcmp(s1, s2, s2_len)) //将s1中的s2_len长度大小的部分与s2比较,看是否相等
return (char *)s1;
s1++; //字符串指针不断后移,要不找到,要不结束
}
return NULL;
}
上面的函数调用了 memcmp()
函数,本着源码分析到底的想法,我们再来看看这个函数是如何实现的。
/**
* memcmp - Compare two areas of memory
* @cs: One area of memory
* @ct: Another area of memory
* @count: The size of the area.
*/
int memcmp(const void * cs,const void * ct,size_t count)
{
const unsigned char *su1, *su2;
int res = 0;
for ( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)//一个个字符比较
{
if ((res = *su1 - *su2) != 0) //若有一个字符不同则立即结束比较操作
break;
}
return res;
}
我们可以看到,由于为了实现简单,C标准库的 strstr()
的运行效率并不是很高效,时间复杂度达到了 O(n^2)
,不过好在空间复杂度只有 O(1)
。