6-4,6-6
今日推荐
搜索文件工具:everything
字符函数和字符串
1、strlen
实现strlen函数的三种方法:
- 计数器的版本
- 递归的版本
- 指针-指针
计数器的版本
#include <stdio.h>
#include <string.h>
#include <assert.h>
int my_strlen(const char* str)
//因为传的是数组名的首地址,所以形参用指针来指向,因为在这个函数里面没有改变这个数组,所以加常量字符串const更加安全
{
int count = 0;//计数器
assert(str != NULL);
while (*str != '\0')
{
count++;
str++;
}
return count;
}
int main()
{
char arr[] = "abc";
//char arr[] = { 'a', 'b', 'c' };//随机值
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
- 用count来记录长度
指针-指针方法
写法1:
//int my_strlen(char* str)
//{
// char* start = str;
// while (*str != '\0')
// {
// str++;
// }
// return str - start;
//}
//
//int main()
//{
// //strlen(); - 求字符串长度
// //递归
// int len = my_strlen("abc");
// printf("%d\n", len);
//
// return 0;
//}
- 刚开始传的是字符串的首地址到strlen函数里面
- 再用指针指向这个起始地址,,再使指针一步步的指向找到字符串的最后一个元素
- 最后两个指针变量相减,就可以求出长度
写法2:
输出>
int main()
{
if (strlen("abc") - strlen("abcdef") > 0)
{
printf(">\n");
}
else
{
printf("<=\n");
}
return 0;
}
- size-t为无符号类型
- my_strlen(“abc”) - my_strlen(“abcdef”)为无符号整数-无符号整数=无符号数,算出-3,但是当作无符号数,它的补码被解析为结果,就会是一个很大的数,输出>
写法3:
输出<=
#include <stdio.h>
#include <string.h>
#include <assert.h>
int my_strlen(const char* str)
{
int count = 0;//计数器
assert(str != NULL);
while (*str != '\0')
{
count++;
str++;
}
return count;
}
int main()
{
if (my_strlen("abc") - my_strlen("abcdef") > 0)
{
printf(">\n");
}
else
{
printf("<=\n");
}
return 0;
}
- 用自己的的my-strlen 解析为有符号数了所以输出<=
递归方法
#include <string.h>
int my_strlen(char* str)
{
if (*str != '\0')
return 1 + my_strlen(str + 1);
else
return 0;
}
int main()
{
char arr[] = "bit";
//['b']['i']['t']['\0']
//
//模拟实现一个strlen函数
printf("%d\n", my_strlen(arr));
return 0;
}
2、strcpy
知识点:
- 字符串:把\0也拷贝过去了
- 字符:没有\0会出错
会将源字符串的\0拷贝到目标空间
int main()
{
char arr[20] = {0};
strcpy(arr, "hello");//string copy
printf("%s\n", arr);
return 0;
}
** 源字符串必须以\0结束**
int main()
{
char arr[20] = "#########";
char arr2[] = { 'a', 'b', 'c' };
strcpy(arr1[], arr2[]);
printf("%s\n", arr);
return 0;
}
- 这里没有\0拷过去,会出错
目标空间必须可修改
int main()
{
char* str = "xxxxxxxxxxxxxxxxxxx";
char* p = "hello world";
strcpy(str, p);
printf("%s\n", arr);
return 0;
}
- 目标空间为常量字符串( char* str = “xxxxxxxxxxxxxxxxxxx”;),指针指向一个常量字符串所以不能修改,会出错
目标空间要足够大,以确保能存放源字符串
int main()
{
char arr[5] = "####";
char* p = "hello world";
strcpy(arr, p);
printf("%s\n", arr);
return 0;
}
- 越界拷贝,目标字符串才5个空间,指针指向的字符串11个字符,拷过去会出错,所以目标空间要足够大
- 虽然会出错但是会强制复制,因为数组作为目标空间的时候是可修改的
3、strcat,连接字符串
把第一个字符的\0覆盖掉,追加在后面,且追加的字符串要有\0并且会追加到过去
模拟实现:
1、找到目标字符串中的\0
2、源数据追加过去,包含\0
3、保证目标空间有足够的空间能让源字符串追加过去
int main()
{
char arr[20] = "abcd";
strcat(arr, arr);//?
printf("%s\n", arr);
return 0;
}
函数模拟实现
char* my_strcat(char* dest, const char*src)
{
char* ret = dest;
assert(dest && src);
1. 找目标字符串中的\0
while (*dest)
{
dest++;
}
2. 追加源字符串,包含\0
while(*dest++ = *src++)
{
;
}
return ret;//返回的目标空间的起始地址
}
int main()
{
char arr1[20] = "hello ";//world
char arr2[] = "world";
my_strcat(arr1, arr2);//字符串追加(连接)
printf("%s\n", my_strcat(arr1, arr2));
return 0;
}
自己追加自己:
不能,\0被改变了,找不到结束的标志\0了
4、strcmp- -比较字符串
两种不用strcmp的错误写法
char* p = "obc";
char* q = "abcdef";
if (p > q)
{
printf(">\n");
}
else
{
printf("<=\n");
}
- 不用字符串函数strcmp比较在这里就会比较的是p和q的地址而不是比较字符串
char* p = "obc";
char* q = "abcdef";
if ("obc" > "abcdef")
{
}
- 比较的是首字符的地址而不是整个字符串的大小
正确的写法
int main()
{
strcmp - 字符串比较大小的
int ret = strcmp("abbb", "abq");//<0
int ret = strcmp("aaa", "aaa");//=0
printf("%d\n", ret);
return 0;
}
实现函数的时候写返回情况
要根据它的三种返回值的情况来写,因为不同编译器可能返回值不一样,但是看到肯定是这三种情况
实现strcmp函数
//写法1
int my_strcmp(const char* s1, const char* s2)
{
assert(s1 && s2);
while (*s1 == *s2)
{
if (*s1 == '\0')//两个相等,且一个等于\0(走到末尾),另一个也\0
{
return 0;//两个相等为0
}
s1++;
s2++;
}
if (*s1 > *s2)//比较ascall值
{
return 1;
}
else
{
return -1;
}
}
//写法2
int my_strcmp(const char* s1, const char* s2)
{
assert(s1 && s2);//后面要进行解引用操作
while (*s1 == *s2)
{
if (*s1 == '\0')
{
return 0;
}
s1++;
s2++;
}
return *s1 - *s2;//返回值有三种情况
}
int main()
{
char* p = "abcdef";
char* q = "abcdef";
int ret = my_strcmp(p, q);
if (ret > 0)
{
printf("p > q\n");
}
else if (ret < 0)
{
printf("p < q\n");
}
else
{
printf("p == q\n");
}
return 0;
}
strncpy
- 复制的字符串的个数小于原有字符串的个数- -正确
int main()
{
char arr1[20] = "abcdef";
char arr2[] = "qwer";
strncpy(arr1, arr2, 2);
printf("%s\n", arr1);//qwcdef
return 0;
}
-
把arr2的前两个字符来覆盖arr1的前两个字符
-
输出qwcdef
-
复制的字符串个数大于字符串原有的个数的时候- -会出错
int main()
{
char arr1[20] = "abcdefghi";
char arr2[] = "qwer";
strncpy(arr1, arr2, 6);
printf("%s\n", arr1);//
return 0;
}
- 虽然会出错但是它实际还是传了6个字符串过去,不够的那两个传的是\0
strncat
当链接过去的的字符串的个数小于自身有的字符串
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world";
strncat(arr1, arr2, 3);
printf("%s\n", arr1);
return 0;
}
- 实现的过程其实是 hello wor\0再把war链接以后就增加\0让它结束
- 输出hello war
当链接过去的的字符串的个数大于自身有的字符串
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world";
strncat(arr1, arr2, 10);
printf("%s\n", arr1);
return 0;
}
- 实现过程(看源函数就可以知道)就是world链接过去以后变为hello world以后加\0让它停止
- 输出hello world
strncmp
int main()
{
char* p = "abcdef";
char* q = "abcqwert";
int ret = strncmp(p, q, 4);
printf("%d\n", ret);
return 0;
}
- 比较两个字符串的前四个字符
- 输出一个小于0的数(不同编译器不一样)