又是好几天没有更新了,最近有些忙,但这并不是理由,还是怪我自己玩的时间多了!但还是有在每天敲代码的!话不多说,开始这一期的学习:
strlen的使用和模拟实现
• 字符串以 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前⾯出现的字符个数(不包含 '\0' )。
• 参数指向的字符串必须要以 '\0' 结束。
• 注意函数的返回值为size_t,是⽆符号的( 易错 )
• strlen的使用需要包含头文件
strlen的使用:
字符串中一共有13个字符,末尾是以\0结尾的,我们strlen函数再计算字符个数时,\0不计入其中,遇到\0才会停下来!如果末尾没有\0的话,strlen就会一直寻找它的\0,直到遇到\0才会停下来,可能会存在越界访问!所以在使用时,一定要注意!而且要加上相应的头文件哦!
strlen的模拟实现:
方法一:
既然它遇到\0就会停止,那么我们就可以创建一个变量(count)来计数,如果arr[i]不为0,那么我们就count++;
#include <stdio.h>
size_t my_strlen(char* str)
{int count = 0;while (*str){count++;str++;}return count;
}
int main()
{char arr[] = "i want to try";size_t len = my_strlen(arr);printf("%zu", len);return 0;
}
方法二:
我们可以利用指针-指针的绝对值等于之间的元素个数来模拟,我们首先保存数组的首元素地址,接着我们找到\0的位置,然后两指针相减就可以知道了。
#include <stdio.h>
size_t my_strlen(char* str)
{char* start = str;while (*str){str++;}return str-start;
}
int main()
{char arr[] = "i want to try";size_t len = my_strlen(arr);printf("%zu", len);return 0;
}
方法三:
第三种方法我们可以利用函数递归的方法进行计算,举个例子:我们要计算的是“hello”这个字符串,那么就是hello-> 1+ello ->1+1+llo ->1+1+1+lo -> +……+1+1+1+1+1+'\0' = 5;
#include <stdio.h>size_t my_strlen(char* str)
{if (*str == '\0'){return 0;}else{return 1 + my_strlen(str + 1);}
}int main()
{char arr[] = "i want to try";size_t len = my_strlen(arr);printf("%zu", len);return 0;
}
strcpy 的使用和模拟实现:
• 源字符串必须以 '\0' 结束。
• 会将源字符串中的 '\0' 拷⻉到⽬标空间。
• ⽬标空间必须⾜够⼤,以确保能存放源字符串。
• ⽬标空间必须可修改。
strcpy 的使用:
我们这时可以打开监视,看一看arr里面的情况,是只拷贝了abcd,还是把'\0'也拷贝了过去!
可以看见是把我们的\0也拷贝过去的,所以这些小细节我们一定要拿捏好,哈哈。
strcpy 的模拟实现:
怎样实现我们strcpy的模拟实现呢?那么就是当我们源字符串不为\0时,我们就改变目的字符串的字符,直到源字符串的字符为0时,我们就跳出循环,接着把\0也copy过去!
#include <stdio.h>
#include <assert.h>char* my_strcpy( char* str1, const char* str2)
{char* ret = str1;//保存str1的首地址,下面需返回首地址打印,ret在下面代码中的位置会被改变assert(str1 && str2);//断言是否为空指针while (*str2 != '\0'){*str1 = *str2;str1++;str2++;}*str1 = *str2;//把\0也拷贝过去return ret;
}int main()
{char arr1[] = "happy new year!";char arr2[] = "hello baby";printf("%s", my_strcpy(arr1, arr2));return 0;
}
其实上述的代码中while部分的代码还可以这样写:
while((*dest++ = *src++)){;}
加加的优先级高于简引用,后置加加所以是先使用再进行加加运算,当*src为\0时,赋值给*dest后,循环条件终止跳出循环!
strcat 的使用和模拟实现:
strcat 的使用:
就是再arr1后面追加arr2的内容,我们去看一看是否把\0也追加了过去!
那么我们可以看见也是把\0追加了过去!那么我们的这个strcat函数,可以自己给自己追加吗?
我们可以看出,\0的位置被改成了b,那么我们的arr2就不会指向我们的\0的位置,就会成为死循环状态,那么对于自己给自己追加的话,我们后面会讲到一种函数(strncat),它就能自己给自己追加!
strcat 的模拟实现:
我们有了上面模拟strcpy的知识,那么对于这个函数,我们就只需要再前面找到arr1\0的位置,然后进行copy就可以了!
#include <stdio.h>
#include <assert.h>
char* my_strcat(char* str1, const char* str2)
{char* ret = str1;assert(str1 && str2);while (*str1){str1++;}//找到str1的\0的位置while (*str1++ = *str2++){;}return ret;
}
int main()
{char arr1[20] = "hello\0xxxxxxx";char arr2[] = "baby";printf("%s", my_strcat(arr1, arr2));return 0;
}
strcmp 的使⽤和模拟实现:
◦ 第⼀个字符串⼤于第⼆个字符串,则返回⼤于0的数字
◦ 第⼀个字符串等于第⼆个字符串,则返回0
strcmp 的使用:
strcmp 的模拟实现:
当我们arr1和arr2指向的位置的字符相等时,我们就指向下一个字符进行比较,当所指向的字符不相等时,我们就比较此时所指向的字符的ASCII值的大小来进行返回值!但是还有一种情况,当我们的arr1所指向的元素为/0时,说明此时已经比较完了,说明两字符串是相等的,那么此时我们就可以返回0!
#include <stdio.h>
#include <assert.h>int my_strcmp(const char* str1, const char* str2)
{assert(str1 && str2);while (*str1 == *str2){if (*str1 == '\0'){return 0;}str1++;str2++;}return *str1 - *str2;/*if (*str1 > *str2)//也可以写成这种{return 1;}else{return -1;}*/
}
int main()
{char arr1[] = "abcd";char arr2[] = "abcd";int ret = my_strcmp(arr1, arr2);if (ret > 0){printf("大于\n");}else if (ret == 0){printf("等于\n");}else{printf("小于\n");}return 0;
}
strncpy 函数的使用和模拟实现:
strncpy 函数的使用 :
我们可以根据打印出来的结果知道,此时并没有把arr2中的copy过去,因为如果copy过去的话,那么我们就只会看见hello!那么我们的num如果大于我们字符串的长度,会是什么结果呢?我们一起来看一看:
我们可以看见当我们的num大于我们的arr2的字符串长度时,我们的\0时拷贝过去了的,那么是拷贝了几个呢?我们一起看看咯:
是两个\0,那么我们就可以知道了:如果源字符串的长度小于num,则拷宝完源字符串之后,在⽬标的后边追加0,直到为num!
strncpy 函数的模拟实现:
我们有了上面模拟strcpy的经验,那么对于此函数我们想要模拟也不难咯!那么当我们的num小于等于我们的字符串的长度时,我们此时就以num为循环条件,当我们的num变为0时,我们就跳出循环,返回arr1的首元素地址:
if (num <= len)
{while (num--){*dest = *src;dest++;src++;}return ret;
}
当大于的时候,我们除了copy完我们arr2的字符外,还要copy我们的\0,那么多出来的此数就copy我们的\0!
else
{while (len--){*dest = *src;dest++;src++;}for (size_t i = a; i < num; i++){*dest = '\0';dest++;}return ret;
}
我们来看看整体的代码:
char* my_strncpy(char* dest, const char* src, size_t num)
{char* ret = dest;assert(dest && src);size_t len = strlen(src);size_t a = len;//保存len的值,下面要用,因为len的值被改变了if (num <= len){while (num--){*dest = *src;dest++;src++;}return ret;}else{while (len--){*dest = *src;dest++;src++;}for (size_t i = a; i < num; i++){*dest = '\0';dest++;}return ret;}
}
int main()
{char arr1[20] = "xxxxxxxxxxxx";char arr2[] = "hello";my_strncpy(arr1, arr2, 7);printf("%s", arr1);return 0;
}
我们还可以用其他的方法,用两个for循环就可以解决问题了:
char* my_strncpy(char* dest, const char* src, size_t n)
{size_t i;for (i = 0; i < n && src[i] != '\0'; i++){dest[i] = src[i];}for (; i < n; i++) {dest[i] = '\0';}return dest;
}
i < n && src[i] != '\0'这样就很好的解决了我们的问题!
strncat 函数的使用和模拟实现:
strncat 函数的使用:
我们的num值为3,那么·追加过去的除了wor三个字符,还有我们的\0。那么如果我们追加的Num值大于字符串长度呢?又会是什么样的结果呢?一起来看一看:
那么可以看见不管多了多少,也只是在后面追加了一个\0!
strncat 函数的模拟实现:
这里就直接展示代码嘛:有了上面的经验,相信大家都是会的吧!
#include <stdio.h>
#include <assert.h>
//方法一:
char* my_strncat(char* dest, const char* src, size_t num)
{char* ret = dest;assert(dest && src);int j = 0;while (dest[j]){j++;}size_t i = 0;for (i = 0; i < num && src[i] != '\0'; i++){dest[j] = src[i];j++;}dest[j] = '\0';return ret;
}//方法二:
//char* my_strncat(char* destination, const char* source, size_t num)
//{
// char* ptr = destination;
// while (*ptr)
// {
// ptr++;
// }
//
// while (*source && num)
// {
// *ptr++ = *source++;
// num--;
// }
//
// *ptr = '\0';
//
// return destination;
//}
//
//int main()
// {
// char str1[30] = "Hello \0xxxxxxxx";
// char str2[] = "World!";
//
// printf("%s\n", my_strncat(str1, str2, 9));
//
// return 0;
//}
strncmp函数的使用:
这里就讲一下怎么使用的,感兴趣的伙伴可以去模拟实现一下看看哦!
相信你们一定可以的!本期的内容就到此了,我们下期再见!