目录
五:strncpy --- 将指定长度的字符串复制到字符数组中
一:strlen --- 求字符串长度
1.简介
2.注意
<1>:字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包 含 '\0' )。
<2>:参数指向的字符串必须要以 '\0' 结束。
<3>:注意函数的返回值为size_t,是无符号的。
判断下述代码的输出结果:
#include<stdio.h>
int main()
{
if (strlen("abc") - strlen("abcde"))
{
printf(">\n");
}
else
{
printf("<=\n");
}
return 0;
}
解:
strlen("abc") 的值为3
strlen("abcde")的值为5
strlen函数的返回值为size_t,是无符号的
3 - 5 = -2 (无符号数) 会转化为一个很大的正数,所以输出结果为 >
3.模拟实现
1.计数器
2.递归
3.指针 - 指针
//模拟实现 strlen 函数
#include<stdio.h>
//计数器
int my_strlen1(char* arr)
{
int count = 0;//计数器
while (*arr != '\0')
{
arr++;
count++;
}
return count;
}
//递归
int my_strlen2(char* p)
{
if (*p != '\0')
{
return 1 + my_strlen2(p + 1);
}
else
{
return 0;
}
}
//指针 - 指针
int my_strlen3(char* pa)
{
char* ret = pa;//保存pa的初始位置
while (*pa != '\0')
{
pa++;
}
return pa - ret;
}
int main()
{
char arr[] = "abcdefgh";
//计数器
int ret1 = my_strlen1(arr);
//递归
int ret2 = my_strlen2(arr);
//指针 - 指针
int ret3 = my_strlen3(arr);
printf("%d\n", ret1);
printf("%d\n", ret2);
printf("%d\n", ret3);
return 0;
}
二:strcpy --- 字符串拷贝
1.简介
char *strcpy( char *strDestination, const char *strSource );
// 目标空间 源字符串
把源字符串拷贝到目标空间中去
2.注意
<1>:源字符串必须以 '\0' 结束。
<2>:会将源字符串中的 '\0' 拷贝到目标空间。
<3>:目标空间必须足够大,以确保能存放源字符串。
需要拷贝 abc ,但是只给了 2 个空间,会引发异常。
<4>:目标空间必须可变。
常量字符串不可以被修改。
3.模拟实现
#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* p1, const char* p2)
//源字符串不发生变化
{
assert(p1 && p2);
char* ret = p1;
/*while (*p2 != '\0')
{
*p1 = *p2;
p1++;
p2++;
}
*p1 = *p2;*/
while (*p1++ = *p2++)
{
;
}
return ret;
//返回的是目标空间的起始地址
}
int main()
{
char arr1[10] = "abcdxxxxxx";
char arr2[] = "qwerty";
my_strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
三:strcat --- 字符串追加
1.简介
char *strcat( char *strDestination, const char *strSource );
// 目标字符串 源字符串
把源字符串追加在目标字符串的末尾
2.注意
<1>:源字符串必须以 '\0' 结束。
由上述可知,字符串追加时从 目标字符串的'\0' 开始追加 ,覆盖 '\0' , 后续追加。
字符串追加时,以源字符串的 '\0' 作为结尾。
<2>:目标空间必须有足够的大,能容纳下源字符串的内容。
<3>:目标空间必须可修改。
<4>:strcat 不可以自己追加自己。
'\0' 会被覆盖掉
3.模拟实现
#include<stdio.h>
#include<assert.h>
char* my_strcat(char* p1, const char* p2)
{
char* ret = p1;
assert(p1 && p2);
//找目标空间中的第一个 '\0'
while (*p1 != '\0')
{
p1++;
}
//拷贝
while (*p1++ = *p2++)
{
;
}
return ret;
}
int main()
{
char arr1[20] = "Hello ";
char arr2[] = "World";
my_strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
四:strcmp --- 字符串比较
1.简介
比较两个字符串的内容,不能使用等号,要使用 strcmp 函数。
int strcmp( const char *string1, const char *string2 );
对应的字符进行比较(ASCII码值)
2.注意
第一个字符串大于第二个字符串,则返回大于0的数字第一个字符串等于第二个字符串,则返回0第一个字符串小于第二个字符串,则返回小于0的数字
a b c d e
a b c q
d < q ---- 返回一个小于0的数字
3.模拟实现
//模拟实现 strcmp
#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* p1, const char* p2)
//字符串进行比较时,不会发生变化,可加上 const 更加安全稳固
{
assert(p1 && p2);
while (*p1 == *p2)//当两个相等时,位于 while 循环内
{
if (*p1 == '\0')
{
return 0;
}
p1++;
p2++;
}
/*if (*p1 > *p2)
{
return 1;
}
else
{
return -1;
}*/
return *p1 - *p2;//等价于,上述 if else
}
int main()
{
char arr1[] = "abcde";
char arr2[] = "abcq";
int ret = my_strcmp(arr1, arr2);
printf("%d\n", ret);
return 0;
}
五:strncpy --- 将指定长度的字符串复制到字符数组中
1.简介
将指定字节的源字符串拷贝到目标字符串中
char *strncpy( char *strDest, const char *strSource, size_t count );
// 目标字符串 源字符串 字节
2.注意
<1>:拷贝num个字符从源字符串到目标空间。
<2>:如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
例下:arr2 有4个,但拷贝了7个
3.模拟实现
//模拟实现
#include<stdio.h>
#include<assert.h>
char* my_strncpy(char* p1, const char* p2, size_t count)
{
assert(p1 && p2);
char* ret = p1;
/*while (count--)
{
*p1++ = *p2++;
}
*/
while (count && (*p1++ = *p2++))//拷贝字符串
{
count--;
}
if (count)//当 count 大于 p2 的长度时,将补充 '\0'
{
while (--count)
{
*p1++ = '\0';
}
}
return ret;
}
int main()
{
char arr1[] = "abcd";
char arr2[] = "qwer";
my_strncpy(arr1, arr2, 1);
printf("%s\n", arr1);
return 0;
}
六:strncat --- 在末尾追加指定大小的字符串
1.简介
char *strncat( char *strDest, const char *strSource, size_t count );
2.注意
<1>:拷贝num个字符从源字符串到目标空间。
<2>:如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个
3.模拟实现
//模拟实现
#include<stdio.h>
#include<assert.h>
char* my_strncat(char* p1, const char* p2, size_t count)
{
char* ret = p1;
assert(p1 && p2);
while (*p1 != '\0')
{
p1++;
}
while (count && (*p1++ = *p2++) != '\0')
{
count--;
}
*p1 = '\0';//字符串追加需要加上一个 '\0'
return ret;
}
int main()
{
char arr1[10] = "abcd";
char arr2[] = "efgh";
my_strncat(arr1, arr2, 2);
printf("%s\n", arr1);
return 0;
}
七:strncmp --- 指定大小,字符串比较
1.简介
int strncmp( const char *string1, const char *string2, size_t count );
2.注意
比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
3.模拟实现
//模拟实现
#include<stdio.h>
#include<assert.h>
int my_strncmp(const char* p1, const char* p2, size_t count)
//给定字符串长度进行比较时,不会发生改变
{
assert(p1 && p2);
while (count-- && (*p1 == *p2) &&(*p1 !='\0') &&(*p2 != '\0'))
{
p1++;
p2++;
if (count == 0)
{
return 0;
}
}
if (*p1 > *p2)
{
return 1;
}
else
{
return -1;
}
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcb";
char arr3[] = "bac";
int ret1 = my_strncmp(arr1, arr2, 3);
int ret2 = my_strncmp(arr1, arr2, 4);
int ret3 = my_strncmp(arr1, arr3, 2);
printf("%d\n", ret1);
printf("%d\n", ret2);
printf("%d\n", ret3);
return 0;
}
八:strstr --- 判断字串
1.简介
char *strstr( const char *string, const char *strCharSet );
strstr(arr1,arr2)判断字符串 arr2 是否为 arr1 的字串
// 若是,则函数返回 str1 字符串从 arr2 第一次出现的位置开始到 str1 结尾的字符串
// 若不是,返回 NULL --- 空指针
2.模拟实现
//模拟实现
#include<stdio.h>
#include<assert.h>
char* my_strstr(const char* p1, const char* p2)
{
assert(p1 && p2);
char* s1 = p1;
char* s2 = p2;
char* ret = p1;//返回的是找到的起始地址
//char* ret = (char*)p1;//更稳固
while (*ret != '\0')
{
s1 = ret;
s2 = p2;
//s2 = (char*)p2;//同上述 ret
while ((*s1 != '\0') && (*s2 != '\0') && (*s1 == *s2))
// 当 s1 / s2 为 \0 时,表示可以停下来 两者相等
{
s1++;
s2++;
}
//*s1 != *s2 时,若 *s2 == '\0',说明,arr2 已经被查找完毕
if (*s2 == '\0')
{
return ret;
}
ret++;//如果 s1 和 s2 不相等
}
return NULL;
}
int main()
{
char arr1[] = "abcdefg";
char arr2[] = "def";
char* ret = my_strstr(arr1, arr2);
if (ret == NULL)
{
printf("找不到\n");
}
else
{
printf("%s\n", ret);
}
return 0;
}
九:strtok --- 分解字符串为一组字符串
1.简介
char * strtok ( char * str, const char * sep );// 字符串 分隔符的集合//"Hello ?World !Hi"// ? ! ---- 分割符//"192.168.121"// . --- 分割符
2.注意
<1>:sep参数是个字符串,定义了用作分隔符的字符集合<2>:第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标 记。<3>:strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注: strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临拷贝的内容 并且可修改。)<4>:strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记(分隔符),strtok函数将保存它字符串中的位置。(返回的为H的地址)<5>:strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标 记。<5>:如果字符串中不存在更多的标记,则返回 NULL 指针。
3.示例
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "Hello ?World !Hi";
char arr[20] = { 0 };//为了保留源数据
strcpy(arr, arr1);//将 arr1 的数据保留到 arr 中去
const char* ret = "!?";
//const --- 限制 ret ,不可被修改
printf("%s\n", strtok(arr, ret));
printf("%s\n", strtok(NULL, ret));
printf("%s\n", strtok(NULL, ret));
return 0;
}
进行优化 --- 后续可以直接添加,不需要增补代码。
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "Hello ?World !Hi?asd";
char arr[40] = { 0 };//为了保留源数据
strcpy(arr, arr1);//将 arr1 的数据保留到 arr 中去
const char* ret = "!?";
char* str = NULL;
for (str = strtok(arr, ret); str != NULL; str = strtok(NULL, ret))
{
printf("%s\n", str);
}
return 0;
}
十:strerror --- 对应错误信息
1.简介
2.注意
返回错误码,所对应的错误信息。
C语言的库函数在调用失败的时候,会将一个错误码存放在:errno 的变量中
当我们想知道调用库函数的时候发生了什么错误信息,就可以将 errno 中的错误码翻译成错误信息。
errno 的头文件为 #include<errno.h>