什么是字符串函数?从字面上理解,就是对字符串函数,那么有哪些字符串函数呢?
通过前面知识的学习,我们知道我们的老朋友strlen是求字符串长度。这是一个很有个性的字符串函数,他只数\0之前的字符个数
头文件:string.h
返回值是:size_t --> 无符号
模拟实现:原理是对字符串数到\0我们就停了不再计数
方法1:计数器
//strlen的模拟实现
//1.循环遍历字符串
size_t mystrlen_1(const char *arr)
{
size_t count = 0;
while (*arr!='\0')
{
count++;
arr++;
}
return count;
}
int main1()
{
char arr[] = "abcdef";
size_t ret = mystrlen_1(arr);
printf("字符串的长度为%zd", ret);
return 0;
}
方法2:指针-指针=元素个数
size_t mystrlen_2(char* arr)
{
char* tmp = arr;
while (*arr != '\0')
{
arr++;
}
return arr - tmp;
}
int main2()
{
char arr[] = "abcdef";
size_t ret = mystrlen_2(arr);
printf("字符串的长度为%zd", ret);
return 0;
}
方法3:递归思想
/法3递归思想
//1+mystrlen_3(arr+1)
//1+1+mystrlen_3(arr+1)
//....
size_t mystrlen_3(char* arr)
{
if (*arr == '\0')
{
return 0;
}
else
{
return 1 + mystrlen_3(arr + 1);
}
}
int main3()
{
char arr[] = "abcdef";
size_t ret = mystrlen_3(arr);
printf("字符串的长度为%zd", ret);
return 0;
}
strcpy:这个函数就是字符串的拷贝。
要求:源字符串必须以'\0'结尾 / 目标空间必须足够大 /目标空间可修改(常量字符串不可修改)
模拟实现:原理是运用双指针将源字符串赋给目标字符串
void mystrcpy_1(char* arr1, char* arr2)
{
assert(arr1&&arr2);
while (*arr2 != '\0')
{
*arr1 = *arr2;
arr1++;
arr2++;
}
*arr1 = *arr2;//\0也要copy
}
void mystrcpy_2(char* arr1, char* arr2)
{
assert(arr1 && arr2);
while (*arr1++=*arr2++)
{
;
}
}
char* mystrcpy_3(char*arr1, char*arr2)
{
char* ret = arr1;
assert(arr1 && arr2);
while (*arr1++ = *arr2++)
{
;
}
return ret;
}
int main()
{
char arr1[20] = { 0 };
char arr2[] = "abcdef";
mystrcpy_2(arr1, arr2);
printf("%s\n", arr1);
printf("%s\n", mystrcpy_3(arr1, arr2));
return 0;
}
strcat:这个函数是用来实现对字符串的追加
要求:源字符串必须以'\0'结束 / 目标空间要足够大且可以修改 / 最好不要自己给自己追加可能发生死循环
模拟实现:原理是先找出目标的‘\0’将其覆盖,再拷贝
strcat的使用及实现
///*char**/void mystrcat_(char* arr1, char* arr2)
//{
// char * ret = arr1;
// assert(arr1 && arr2);
// //1.找到\0
// while (*arr1)
// {
// arr1++;
// }
// //2.拷贝
// while (*arr1++ = *arr2++)
// {
// ;
// }
// /*return ret;*/
//
// }
//
//int main()
//{
// //目标要足够大
// char arr1[20] = "hello ";
// char arr2[] = "world";
// mystrcat_(arr1, arr2);
// printf("%s\n",arr1);
// return 0;
//}
strcmp:这个函数是用来比较字符串
特点:比较对应位置的字符ascii码。例如“abcd"和”abcq",前面的都相同,d和q不同,d的ASCII码小于q的,所以小于
返回类型是:size_t
模拟实现:原理是一个一个比较,找到不同的位置,再进行比较。这里的优化可以用指针-指针,因为小于返回的是负数,大于返回正数
int mystrcmp_1(const char*s1,const char* s2)
{
while (*s1 == *s2)
{
if (*s1 == '\0')
{
return 0; //相同情况
}
s1++;
s2++;
}
if (*s1 > *s2)
{
return 1;
}
else
{
return -1;
}
}
int mystrcmp_2(const char* s1, const char* s2)
{
while (*s1 == *s2)
{
if (*s1 == '\0')
{
return 0; //相同情况
}
s1++;
s2++;
}
return *s1 - *s2;//一样的 大于返回正数 小于返回负数 以ASCII码值计算
}
//一个一个位置比较
int main2()
{
char arr1[] = "bbq";
char arr2[] = "abcd";
int ret = mystrcmp_2(arr1, arr2);
if (ret > 0)
{
printf("大于\n");
}
else if (ret < 0)
{
printf("小于\n");
}
else
{
printf("等于\n");
}
return 0;
}
strncpy:这个函数在strcpy的基础上有copy个数限制
特点:当长度不够时,会用‘\0'来补充。你要拷贝几个就几个。
模拟实现:
/模拟实现strncpy
char* mystrncpy(char* dest, char* src, size_t num)
{
char* tmp = dest;
assert(dest && src);
size_t len = strlen(src);
size_t count = num ;
while (count--)
{
if (count > len)
{
*(src + count) = '\0';
}
*(dest+count) = *(src + count);
}
return tmp;
}
int main5()
{
char arr1[] = "hello";
//char arr2[20] = "bitxxxxx";
char arr2[20] = { 0 };
size_t n = 0;
scanf("%zd", &n);
printf("%s\n", mystrncpy(arr2, arr1, n));
return 0;
}
strncat:这个函数是在strcat的基础上进行追加个数的限制
特点:当追加长度小于源字符串,他不会给你多加。每次追加完都会给你带个\0
模拟实现:
//模拟实现strncat 特点是你要追加几个就几个,搞完给你来个\0,之后没用\0补
char* mystrncat(char* dest, char* src, size_t n)
{
size_t count = n;
char* tmp = dest;
assert(dest && src);
//1.找目标\0
while (*dest)
{
dest++;
}
//2.拷贝
while (*dest++ = *src++ && count--)
{
;
}
return tmp;
}
int main()
{
char arr1[20] = "hello";
char arr2[20] = "world";
size_t n = 0;
scanf("%zd",&n);
printf("%s\n", mystrncat(arr1, arr2, n));
return 0;
}
strncmp:比较arr1和arr2的前n个字符
strstr:这个函数是用来从目标字符串找源字符串的。
特点:函数返回的是源字符串在目标字符串第一次出现的位置/匹配不包括\0,以\0为结束标志
模拟实现:运用双指针和一个临时变量来记录位置,一个地方为起始位置不匹配就移动这个临时变量来更新起始位置。
//模拟实现strstr这个字符串函数的功能是从目标字符窜找出源字符串的位置
char* mystrstr_(char* dest,char*src)
{
assert(dest && src);
if (src == '\0')
{
return NULL;
}
char* cur = dest;
char* s1 = NULL;
char* s2 = NULL;
while (*cur)
{
//让cur作为记录位置的指针
//abbbcdef
//bbc
s1 = cur;
s2 = src;
while (*s1 == *s2)
{
s1++;
s2++;
}
//最后如果找到,就会加到\0
if (*s2 == '\0')
{
return cur;
}
cur++;//不匹配移动
}
return NULL;
}
int main1()
{
char arr1[20] = "abbbcdef";
char arr2[] = "bbc";
printf("%s\n", mystrstr_(arr1, arr2));
return 0;
}
strtok:这个函数用来分割字符串
特点:
int main4()
{
char arr[] = "[email protected]";
char* p = "@.";
char* s = NULL;
for (s = strtok(arr, p);s!=NULL;s=strtok(NULL,p))
{
printf("%s\n", s);
}
return 0;
}
strerror: strerror函数可以把参数部分错误码对应的错误信息的字符串地址返回来。
错误码⼀般是放在 errno.h 这个头⽂件中说明 的,C语⾔程序启动的时候就会使⽤⼀个全⾯的变量errno来记录程序的当前错误码,只不过程序启动 的时候errno是0,表⽰没有错误,当我们在使⽤标准库中的函数的时候发⽣了某种错误,就会讲对应 的错误码,存放在errno中,⽽⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址返回。
应用:
//strerror perror
#include
int main9()
{
int i = 0;
for (i = 0; i <= 100; i++)
{
printf("%d:%s\n", i, strerror(i));
}
return 0;
}
int main()
{
FILE* pfile;
pfile = fopen("unexist.ent","r");
if (pfile == NULL)
{
printf("Error openning file unexist.ent:%s\n", strerror(errno));
}
return 0;
}
memcpy函数操作单位是字节,通过内存进行copy
特点:遇到\0不会停下继续拷贝,内存重叠和不重叠都可以实现copy
模拟实现:此代码无法实现内存重叠 原理是以1个字节为单位交换
//memcpy的实现
void* mymemcpy_(void* dest, void* src, size_t num)
{
assert(dest && src);
void* tmp = dest;
while (num--)
{
//char为1个字节,比较简便
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return tmp;
}
int main2()
{//以内存来copy
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 2,3,4,5,6};
mymemcpy_(arr1, arr2, 5 * sizeof(int));
for (int i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
memmove:专门用来处理内存重叠
模拟实现:对dest在src前,采用从前往后copy;对dest在src后,采用从后往前copy
//memmove 内存重叠
//1 2 3 4 5 6 7 8 9 10
//dest在src前采用前-后打印
//dest在src后采用后-前打印
void* mymemmove_(void*dest,void*src,size_t num)
{
void* tmp = dest;
if (dest < src)
{
//前-后
while (num--)
{
//char为1个字节,比较简便
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
//后-前
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
//num--一直往后推进
}
}
return tmp;
}
int main3()
{
int arr1[10]={1,2,3,4,5,6,7,8,9,10};
int arr2[10] = { 1,2,3,4,5,6,7,8,9,10 };
mymemmove_(arr1 , arr1+3, 5 * sizeof(int));//destsrc
for (int i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
printf("\n");
for (int i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
分享到此结束啦,感谢各位!