开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情
前言
本文介绍一下C语言字符串库函数中长度不受限的字符串函数。
新手一个,水平比较低,还请包涵。
长度不受限的字符串函数
所在头文件: <string.h>
顾名思义,这一类函数对字符串进行操作的时候总是以'\0'为基准进行的,长度往往不受限制,容易造成越界。
strlen函数
相关描述
函数原型:size_t strlen( const char *string );
函数功能:计算字符串长度,直到遇到空字符结束,但不包括空结束字符。
函数说明:
strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。
参数指向的字符串必须要以 '\0' 结束。
注意函数的返回值为size_t,是无符号的(易错)。
返回类型:size_t (strlen特有的非负整数类型)
看看这个,是不是觉得打印出<=?要这么想你就掉进坑里了。
strlen返回值是无符号整型,3-6你以为会是-3,实际上并不是,这里可不是有符号整型的计算,它们的补码相减运算后得到的数被认为是无符号数,这里会得到一个很大的正数,必然是>0的。
模拟实现
迭代计数法
size_t MyStrlen(const char* dest)
{
assert(dest != NULL);
size_t cnt = 0;
while (*dest != '\0')
{
count++;
dest++;
}
return cnt;
}
递归计数法
size_t MyStrlen(const char* dest)
{
assert(dest != NULL);
if (*dest)
return 1 + MyStrlen(dest + 1);
else
return 0;
}
指针相减法
size_t MyStrlen(const char* dest)
{
assert(dest != NULL);
const char* tmp = dest;
while (*(++dest)); //一直后移直到遇见空字符
return dest - tmp;
}
strcpy函数
相关描述
函数原型:char *strcpy( char ***** strDestination , const char ***** strSource );
函数功能:把一个字符串(后面的源字符串)拷贝到另一个字符串(前面的目标字符串)中
函数说明: 源字符串必须以 '\0' 结束。
拷贝时会将源字符串中的 '\0' 拷贝到目标空间。
目标空间必须足够大,以确保能存放源字符串。 目标空间必须可变,也就是说不能是字符串字面量。
返回类型:char*
模拟实现
char* MyStrcpy(char* dest, const char* src)
{
assert(dest != NULL);
assert(src != NULL);
char* ret = dest;
while (*dest++ = *src++)//包括了把空字符也拷过去
{
;
}
return ret;
}
strcmp函数
相关描述
函数原型:int strcmp(const char *string1, const char *string2);
函数功能:比较两字符串,实际上是通过字符比较实现的
返回类型:int
字符比较(character comparison)是指按照字典次序对单个字符或字符串进行比较大小的操作,一般都是以ASCII码值的大小作为字符比较的标准。
字符串比较的时候,字符串的大小是从最左边第一个字符开始比较,大者为大,小者为小,若相等,则继续比较后面的字符;
比如ABC与ACDE比较,第一个字符相同,继续比较第二个字符,由于第二个字符是后面一个串大,所以不再继续比较,结果就是后面个串大。
再如ABC与ABC123比较,比较三个字符后第一个串结束,所以就是后面一个串大。
所以,长度不能直接决定大小,字符串的大小是由左边开始最前面的字符决定的。
注意:
当字符串有空格时,空格也参加比较。
由汉字组成的字符串可以参加比较。如”李红”<”王军”。它们的大小实际是由其拼音构成的字符串的大小来决定的,即:”LIHONG”<”WANGJUN”。
返回值对应不同的字符串关系
其中返回值为0说明两字符串内容完全相同。
模拟实现
int MyStrcmp(const char* str1, const char* str2)
{
assert(str1 != NULL);
assert(str2 != NULL);
while(*str1 == *str2)
{
if(*str1 == '\0')
return 0;
str1++;
str2++;
}
return *str1 - *str2;
}
strcat函数
相关描述
函数原型:char* strcat(char *strDestination, const char *strSource);
函数功能:字符串追加,就是把一个字符串接到另一个字符串的尾巴上去。
strcat函数将字符串strSource附加到字符串strDestination后面,并使用空字符终止生成的字符串。strSource的初始字符覆盖strDestination的终止空字符。
函数说明:
源字符串必须以 '\0' 结束。
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。
复制或追加字符串时不执行溢出检查。
字符串自己给自己追加,如何?
如果源字符串和目标字符串重叠,则strcat的行为未定义。
返回类型:char*
模拟实现
char* MyStrcat(char* dest, const char* src)
{
assert(dest != NULL);
assert(src != NULL);
char* ret = dest;
while(*(++dest))
{
;
}
while(*dest++ = *src++)
{
;
}
return ret;
}
strstr函数
相关描述
函数原型:char* strstr( const char *string, const char *strCharSet);
函数功能:在字符串string中寻找第一次出现的子字符串strCharSet,如果找到返回对应地址,如果找不到返回空指针。
返回类型:char*
模拟实现
BF算法(暴力匹配)
前置思考:
两个指针分别指向总字符串和子字符串,将元素一一进行比对,不相同的话str后移,相同的话str和substr同时后移,直到substr遇到空字符,这时就说明找到了。
那有没有一种可能,就是说前几个字符都对上了,但是后面的对不上,也就是第一次匹配没匹配上,这时候该怎么处理呢?
那就不止设置一个循环。
实现思路:
用cur指针存放当前总字符串指向位置的地址,再用s1,s2两个指针分别对总字符串和子字符串中的字符进行比对,两指针未移动到字符串的末尾的前提下,若是字符相同则移动至下一个再比对,当s2遇到空字符时说明找到了子字符串,此时直接返回cur指针内容。
实现代码:
char* MyStrstr(const char* str, const char* substr)
{
//指针有效性检测
assert(str != NULL);
assert(substr != NULL);
const char* s1 = NULL;
const char* s2 = NULL;
const char* cur = str;
//子字符串为空时
if ('\0' == *substr)
{
return (char* )str;
}
while (*cur)
{
s1 = cur;
s2 = substr;
while (*s1 && *s2 && *s1 == *s2)
{
s1++;
s2++;
}
if ('\0' == *s2)
{
return (char*)cur;
}
cur++;
}
return NULL;
}