- 字符串函数
- 长度不受限的字符串函数
- strlen
- strcpy
- strcat
- strcmp
- 长度受限的字符串函数:
- strncpy
- strncat
- strncmp
- strstr
- strtok
- strerror
- 内存操作函数
- memcpy
- memmove
- memcmp
- memset
- 字符串函数的模拟实现和注意
- strlen模拟实现
- strcpy模拟实现
- strcat模拟实现
- strcmp模拟实现
- strstr模拟实现
- memcpy模拟实现
- memmove模拟实现
strlen的作用就是求字符串长度,从开始位置一直计数到 之前,返回的是 之前出现的字符个数。
strlen返回的是无符号数,所以如果比较两个字符串长度的时候不可以用strlen相减,因为无符号数-无符号数最后还是无符号数。
int main()
{
if(strlen("abc")-strlen("abcd")<0)
printf("<");
return 0;
}
strcpy
字符串拷贝函数,函数原型为:
strcat因为source是不会被修改的所以加上source修饰。
注意:这里的source必须是以 结尾的,不然拷贝找不到 停不下,就会越界
拷贝会连着src末尾的 一起拷贝过去。
dest的空间必须足够大,可以容纳下src
dest的空间必须可以修改,不可以是常量字符串
字符串追加函数:
strcmp将src这个字符串追加到dest后面,从dest的 开始,最后会连同src的 一同追加过去。
这里注意,strcat不可以自己给自己追加,因为追加的第一个字符覆盖了 ,这样子src就找不到 了,就会陷入死循环最后越界。
注意:
目标空间必须足够大可以容纳下两个字符串的内容,目标空间必须可以修改。
源字符串必须有 ,不然就会越界。
长度受限的字符串函数:比较两个字符串的大小,比较原理是,先比较第一个字符的ASCII码值,如果相同就比较第二个字符,直到两个字符串都到了 ,或者遇到不相等的字符,根据ascii码值,如果第一个字符串的这个字符的ASCII码值大就返回>0的数字,如果小就返回小于0,相等的时候会返回0.
strncpy上面介绍的字符串函数都是长度不受限制的字符串函数,下面这些都是长度受到限制的字符串函数。我们知道长度不受限制很可能会出现安全隐患,比如,拷贝和字符串连接的时候目标空间够。这时候可以用strncpy进行字节决定长度的拷贝或者连接。
strncat该函数的作用就是将源字符串的前num个字节拷贝到dest处,如果num大于src的长度,这时候会在拷贝完之后在dest后面追加 直到数目达到num。
strncmp在dest后面连接num字节数个src的字符。如果src的长度小于num那么只连接到src的 处(也即是全部将src追加过去),就相当于是strcat了。这个函数也和strcat一样都会在末尾补上 。
比较两个字符串的前n个字节的字符
strstr这个就是比较两个字符串的前num个字符,直到遇到不相等的字符串或者是遇到字符串结束,或者是达到了num个。
查找子串
strtok在str1中查找str2这个子字符串,如果找到了就返回这个子字符串在str1中的首地址,找不到就返回空指针。
字符串分割函数
del字符串保存了分割字符串,就是作为分隔符的字符的集合。
注意:这个函数分割字符串的时候会改变原来的字符串,所以一般是使用拷贝的字符串进行分割。所以str不可以是常量字符串。
该函数找到了分隔符之后会将分隔符置为 ,然后返回这个分隔符前的字符串的首地址。并且函数会保存在字符串中的位置。下次寻找分割符的时候直接从该位置向后查找。所以下一次查找的时候第一个参数就不需要了,只需要传空指针即可。
int main()
{
char arr[] = "hello@world&kisskernel";
char copy[40];
strcpy(copy, arr);
for (char* ret = strtok(copy, "@&"); ret != NULL; ret = strtok(NULL, "@&"))
{
printf("%sn", ret);
}
return 0;
}
strerror如果最后查找不到了就会返回NULL,这里如果多个分隔符连在一起比如@@或者@&&&,这种只有第一个分隔符有效剩下的忽略掉,因为这每两个分隔符之间没有字符串,所以也不会额外打印出来空行
内存操作函数这个函数就是返回错误码对应的错误信息。C语言中如果程序执行过程中遇到错误就会生成一个错误码,并且保存在全局变量errno中,所以只要引用头文件#include
然后给strerror传参errno即可打印出来错误信息。
memcpy上面的函数只能操作字符串,那么int,float等其他的类型的数组该怎么操作呢?这就用到了内存操作函数。
内存拷贝函数:
memmove将src的前num个字节拷贝到dest中最后返回的是dest的地址。该函数不管什么情况总是将src的num个字节拷贝到dest中,所以至少以保证dest的空间要是大于num的src的有效字节数也应该是大于等于num的。同时dest和src不可以是重叠的,如果重叠的拷贝使用memmove会更安全,因为如果内存重叠,memcpy默认从前向后拷贝就会将要拷贝过去的数据修改。
例如将:[1,2,3,4,5,6,7,8,9]将这个数组的1234拷贝到3456的位置,在拷贝12的时候已经将34改成了12,所以后面的拷贝会让56也变成12。
上面的memcpy不能拷贝发生重叠的数据,所以库函数提供了memmove来处理重叠的数据拷贝,在vs编译器里面memcpy可以拷贝重叠数据就是实现了memmove的功能,但是C语言标准规定memcpy只需要实现不重叠的内存拷贝即可。
memcmpmemmove的使用方法是和memcpy一样的。
内存比较函数,比较两块内存空间的内容,注意这里的比较方法是每个字节每个字节的比较。
memset如果两块内存空间相等就返回0,这个函数直到将所有num字节比较完,或者是遇到不相等的字节就停下来。
ptr1>ptr2的某个字节就返回>0的数字,ptr1
字符串函数的模拟实现和注意 strlen模拟实现内存设置函数,可以将ptr的num字节全部设置成为value,要注意设置int的时候如果value是1,并不是吧每个元素都初始化成1,而是这个元素的每个字节都是1。
这里实现strlen有三种方式
1,循环
2,递归(不创建变量)
3,指针-指针
size_t my_strlen(const char* str)
{
assert(str);
size_t count = 0;
while (*str)
{
count++;
str++;
}
return count;
}
断言要注意,str不能是空指针所以需要断言。然后就让指针不等于 不断向后移动,计数器++,最后返回计数器的值。
//递归
int my_strlen1(const char* str)
{
assert(str);
if (*str == ' ')
return 0;
else
return 1 + my_strlen1(str + 1);
}
//指针-指针
int my_strlen2(const char* str)
{
assert(str);
char* begin = str;
while(*str!=' ')
{
str++;
}
return str - begin;
}
strcpy模拟实现
char* my_strcpy(char* des, const char* sur)
{
assert(des && sur);
char* ans = des;
while (*des++ = *sur++)
{}
return ans;
}
strcat模拟实现这里的实现很巧妙,用while判断条件,先将sur的值拷贝过去,然后判断sur是不是为 ,不是 就继续,是 就会退出循环,因为 的ASCII码值就是0,所以可以直接当作判断为假的条件。这样可以省去最后再补上 这一句代码。
char* my_strcat(char* dest, const char* src)
{
assert(dest && src);
char* ans = dest;
while(*(++dest))
{ }
while (*dest++ = *src++)
;
return ans;
}
strcmp模拟实现思路就是,先找到dest的 位置然后进行字符串拷贝。要连着src的 一起拷贝过去。
int my_strcmp(const char* str1, const char* str2)
{
assert(str1 && str2);
while (*str1 == *str2 && *str1!=' ')
{
str1++;
str2++;
}
return *str1 - *str2;
}
思路就是循环比较两个字符串对应字符,相等就继续,直到字符串不相等或者str1遇到了 就跳出循环。为什么str1遇到 就跳出循环?str2遇到 呢?这里写str1或者str2都是可以的。因为这里情况:如果str1先遇到 ,这时候str2不为 ,不相等,跳出循环,str2遇到 也是这样。如果两个同时遇到 这时候还是相等的,但是不可以继续++了需要第二个str1!= 这个条件跳出循环。
最后返回两个的差值就可以了。str1大差值为+,str2大差值为-,str1str2


