- strlen
- strcpy
- strcat
- strcmp
- strncpy
- strncat
- strncmp
写在前面:本文比较长,覆盖了c语言中较多的字符串函数,作者会先带各位了解标准库对函数的介绍,然后模拟实现相关功能。
strlen
求字符串长度
size_t表明返回一个无符号类型的数字,是因为考虑到length为非零整数
const 可以保护str指向的那块空间不被改变,因为我们只是去求字符串的长度,而不会去解引用改变内容
注意
看这样一段代码
#include<stdio.h>
#include <string.h>
int main(void)
{
if (strlen("ab") - strlen("abc") > 0)
{
printf(">");
}
else
{
printf("<");
}
return 0;
}
打印结果为“>”
原因是strlen的返回值是无符号类型的,此处结果是应该一个负数,在内存中存的是补码,但和0比较的时候,由于是无符号类型,所以被解读为一个很大的数字,远远大于了0
模拟
方法1(计数器)
#include <stdio.h>
#include <assert.h>
int my_strlen(const char* p)
{
assert(p);
int ret = 0;
while (*p++){
ret++;
}
return ret;
}
int main(void)
{
char* p = "string";
printf("%d ", my_strlen(p));
return 0;
}
方法2(递归)
//2.递归
int my_strlen(const char* p)
{
if (*p)
return 1 + my_strlen(++p);
else
return 0;
}
方法3(指针-指针)
这种方法和VS2022库函数文件里的写法一样,所以我们参考微软工程师的代码
size_t __cdecl strlen (
const char * str
)
{
const char *eos = str;
while( *eos++ ) ;
return( eos - str - 1 );
}
strcpy
拷贝字符串
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
int main(void)
{
char* arr1 = "abcd";
char arr2[20] = { 0 };
strcpy(arr2, arr1);
printf("%s", arr2);
return 0;
}
注意
如你所见,
1.arr2是被拷贝的空间,要求可以改变,应该是数组,而对源字符串不作要求,可以是字符指针指向的字符串常量,也可以是数组。
2.拷贝字符串以源字符串中的‘\0’结束。
可验证:
3.作为合格的程序员,你得保证目标空间可以存下你要拷贝的东西。(不要写bug)
模拟
char* my_strcpy(char* dest, const char* src)
{
assert(dest && src);
char* p = dest;
while (*dest++ = *src++);
return p;
}
int main(void)
{
char arr1[] = "abcdd";
char arr2[20] = { 0 };
my_strcpy(arr2, arr1);
printf("%s", arr2);
return 0;
}
strcat
字符串追加
这个函数对’\0’要求很大,目标字符串和源字符串都得有’\0’。
模拟
char* my_strcat(char* dest, const char* src)
{
assert(dest && src);
char* p = dest;
while (*dest) {
dest++;
}
while (*dest++ = *src++);
return p;
}
注意
不要拿这个函数给自己追加,因为会覆盖\0,不能结束追加。
strcmp
是他!就是他!
比较字符串大小
需要对返回值做一下说明:
比如“abcdef”和
"abu’,虽然前者比后者在长度上大得多,但比较字符串是对应位置依次比较,在‘u’和’c’处u> c,所以比较结束,前者小于后者,返回一个小于零的值
话不多说,直接模拟
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
int my_strcmp(const char* p1, const char* p2)
{
assert(p1 && p2);
while (*p1 == *p2)
{
p1++;
p2++;
}
if (!*p1)
return 0;
else
return *p1 - *p2;
}
int main(void)
{
char* p = "tomota";
char* q = "tomoto";
if (my_strcmp(p, q) > 0)
printf(">");
else if (my_strcmp(p, q) < 0)
printf("<");
else
printf("=");
return 0;
}
strncpy
说明
正常使用
你非要写BUG
目标空间不够用,你非要拷?
小手一抖,一个BUG
既然不够,拿0来凑
strncat
追加时,覆盖0,自己补0
不够追加直接补个结束标志
这小子发现自己“追”不上,就给了0然后跑路了
strncmp
很简单,多的一个参数就是用来指定比较前“几”个字符
自己用着看