一、求字符串长度的函数
strlen
二、长度不受限制的字符串函数
strcpy
strcmp
strcat
三、长度受限制的字符串函数
strncpy
strncat
strncmp
四、字符串查找
strstr
strtok
五、错误信息报告
strerror
一、求字符串长度的函数
strlen
注意:
1.strlen函数返回的是字符串中'\0'前面出现的字符个数(不包含'\0')
2.该函数的参数类型是一个char类型的指针,返回值是size_t(无符号整形)
3.因为返回值是size_t,所以不能用函数的返回值相比较或做运算
(挖个坑) strlen的模拟实现(1.计数器的方式 2.递归的方式 3.指针减去指针的方式)
二、长度不受限制的字符串函数
1.字符串拷贝函数
strcpy
注意:1.要保证目标空间足够大
2.目标空间必须可变,因此不能在第一个参数前加const
参数类型:1.char *strDestination
2.char *strSource
返回类型:char*
strcpy的模拟实现
普通版(已引头文件):
//strcpy的模拟实现
void my_strcpy(char *dest, char *src)
{
while (*src != '\0')
{
*dest = *src;
src++;
dest++;
}
*dest = *src;
}
int main()
{
char arr1[20] = "#########";
char arr2[20] = "hello world";
my_strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
高级版:
//strcpy的模拟实现
#include<string.h>
#include<assert.h>
char* my_strcpy(char *dest,const char *src)
{
assert(dest && src);//断言,提高指针的安全性
char *ret = dest;
while (*dest++ = *src++)//字符串的拷贝,先拷贝,后++,当把'\0'也拷贝过去后,括号里表达式结果为0,为假,跳出循环
{
;
}
return ret;//返回目标空间的起始地址
}
int main()
{
char arr1[20] = "#########";
char arr2[20] = "hello world";
my_strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
2.字符串追加函数
strcat
注意:1.要追加的目标空间必须足够大
2.要追加的空间必须可修改
3.目标字符串和源字符串必须要有'\0'
4.不能自己给自己追加
参数:1.char *strDestination
2.char *strSource
返回类型:char*
模拟实现
//strcat的模拟实现
#include<assert.h>
char* my_strcat(char *dest, const char *src)
{
assert(dest && src);
char *ret=dest;
//1.找到目标字符串的'\0'
while (*dest)
{
dest++;
}
//2.追加
while (*dest++ = *src++);
{
;
}
return ret;
}
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world";
printf("%s\n", my_strcat(arr1, arr2));
return 0;
}
3.字符串比较函数
strcmp
注意:
1.比较的是对应的字符的ASCII码值,不是比较字符串长度
2.前者>后者,返回一个>0的数;前者=后者,返回0;前者<后者,返回一个<0的数
参数:1.char *str1
2.char *str2
返回类型:int
模拟实现
//strcmp的模拟实现
#include<assert.h>
int my_strcmp(const char *s1, const char *s2)
{
assert(s1 && s2);
while (*s1 == *s2)
{
if (*s1 == '\0')
return 0;
s1++;
s2++;
}
return *s1 - *s2;
}
int main()
{
char arr1[10] = "abc";
char arr2[10] = "abcde";
int ret = my_strcmp(arr1, arr2);
printf("%d\n", ret);
return 0;
}
三、长度受限制的字符串函数(与受限制的函数相比多了一个参数size_t count,用来记录要操作的字符个数)
与长度不受限制的函数差不多,较简单,不做过多说明
四、字符串查找函数
1.strstr(查找子串)
能找到的情况:
//strstr查找子串函数
#include<string.h>
int main()
{
char arr1[20] = "abcdef";
char arr2[20] = "bcde";
char *ret = strstr(arr1, arr2);//在arr1中查找arr2第一次出现的位置,并返回arr1中第一个被查找的字符的首地址,将该地址打印后可打印出arr1从该字符起之后的字符串
printf("%s\n", ret);//bcdef
return 0;
}
判断能否找到的情况:
//strstr查找子串函数
#include<string.h>
int main()
{
char arr1[20] = "abcdef";
char arr2[20] = "bcde";
char *ret = strstr(arr1, arr2);//在arr1中查找arr2第一次出现的位置,并返回arr1中第一个被查找的字符的首地址,将该地址打印后可打印出arr1从该字符起之后的字符串
if (ret != NULL)
printf("%s\n", ret);//bcdef
else
printf("找不到\n");
return 0;
}
模拟实现(难点)
//strstr模拟实现
#include<assert.h>
char* my_strstr(const char *s1,const char *s2)
{
assert(s1 && s2);//断言
const char *cp = s1;
if (*s2 == '\0')
return (char*)s1;//特殊情况
while (*cp)//判断*cp是否等于\0
{
const char *p1 = cp;
const char *p2 = s2;
while ((*p1) && (*p2) && (*p1 == *p2))
{
p1++;
p2++;
}
if (*p2 == '\0')
return (char*)cp;
cp++;
}
return NULL;
}
int main()
{
char arr1[20] = "abbbcdef";
char arr2[20] = "bbc";
char *ret = my_strstr(arr1, arr2);
if (ret != NULL)
printf("%s\n", ret);
else
printf("找不到子串\n");
return 0;
}
2.strtok(切割字符串)
//strtok
#include<string.h>
int main()
{
char arr1[30] = "123456.3.haha@qq";
char arr2[30] = { 0 };
char p[30] = ".@";
strcpy(arr2, arr1);//将arr1拷贝到arr2,使得arr1得以保留,我们操作arr2
char *ret;//接收strtok函数的返回值,为一个指针
//用循环的方式打印,第一次调用的时候第一个参数传参要传字符串,之后只用传空指针就可以
for (ret = strtok(arr2,p); ret != NULL; ret = strtok(NULL, p))
{
printf("%s\n", ret);
}
return 0;
}
strtok函数的古怪之处在于它第一次调用的时候第一个参数传参要传字符串,而之后只用传空指针,这是static的功劳,它帮助strtok函数每次调用之后都能保留原来指针的位置,而它开辟的内存不会随着调用的结束而销毁。
五、错误报告函数
strerror
功能:把错误码转换为对应的错误信息,返回错误信息对应字符串的起始地址