字符函数和字符串函数 下

在这里插入图片描述

前言

本文是 继续 字符函数和字符串函数
上文 链接
字符串和字符串函数 上

一、strstr

1.strstr函数

头文件<string.h>

2.描述

char *strstr(const char *haystack, const char *needle) 
在字符串 haystack 中查找第一次出现字符串 needle 的位置,不包含终止符 '\0'。
haystack -- 要被检索的 主 字符串。
needle -- 在 haystack 字符串内要搜索的子字符串。

.返回值

该函数返回在 haystack 中第一次出现 needle 字符串的位置,如果未找到则返回 null。

2.strstr函数的使用

#include<stdio.h>
#include<string.h>

int main()
{
	char arr1[20] = "abbbcdef";
	char arr2[10] = "bcd";
	char* ret = strstr(arr1, arr2);
	// strstr 函数 没找到 会 返回 空指针 NULL
	if (ret == NULL)
	{
		printf("没找到\n");
	}
	else
	{
		printf("子字符串->: %s ", ret);
	}
	return 0;
}

3.strstr模拟实现

#include<stdio.h>
#include<string.h>
#include<assert.h>
char* my_strstr(const char* arr1, const char* arr2)
{
	assert(arr1 && arr2);
	const char*s1 = NULL;
	const char* s2 = NULL;
	char* cp = arr1;
	while (*cp)
	{
		s1 = cp;// cp 记录 arr1 的位置如果需要回退则会回到此位置
		s2 = arr2;
		while (*s1 && *s2 && (*s1 == *s2))
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return cp;
		}
		cp++;
	}

}
int main()
{
	char arr1[20] = "abbbcdef";
	char arr2[10] = "bcd";
	char* ret = my_strstr(arr1, arr2);
	// strstr 函数 没找到 会 返回 空指针 NULL
	if (ret == NULL)
	{
		printf("没找到\n");
	}
	else
	{
		printf("子字符串->: %s ", ret);
	}
	return 0;
}

花了草图思路 ,水平有限
只能将就看看了
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、strtok

1.strtok函数

原型

头文件 <string.h>
char * strtok ( char * str, const char * sep );

sep参数是个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标

strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:
strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容
并且可修改。)
strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串
中的位置。
strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标
记。
如果字符串中不存在更多的标记,则返回 NULL 指针。

2.strtok的使用

#include<stdio.h>
#include<string.h>
// strtok  会将 第二个数组 中存放 的字符当分割标识
// 如 下面的" " "." "@"  strtok 会改变 原来的数组
// 所以 可以先用 strcpy 先拷贝一份 然 让 strtok 分割
// 拷贝的数组 strtok 会先重左到右找到表示符号 并把标识符改成'\0'并将地址记住
// 返回 第一个元素地址,
//当第二个 参数 传的为NULL 函数将在同一个字符串中被保存的位置开始(上次记录的地址),查找下一个标
//记。
//int main()
//{
//     char arr1[] = "wan quan@qq.haha";
//     char* p = " .@";
//     char tmp[20] = { 0 };
//     strcpy(tmp, arr1);
//     char* ret = NULL;
//      ret = strtok(tmp, p);
//      printf("%s\n", ret);
//      ret = strtok(NULL, p);
//      printf("%s\n", ret);
//      ret = strtok(NULL, p);
//      printf("%s\n", ret);
//      ret = strtok(NULL, p);
//      printf("%s\n", ret);
//
//     return 0;
//}
//
int main()
{
       char arr1[] = "wan quan@qq.haha";
              char* p = " .@";
              char tmp[20] = { 0 };
              strcpy(tmp, arr1);
              char* ret = NULL;
              for (ret = strtok(tmp, p); ret != NULL; ret = strtok(NULL, p))
              {
                     printf("%s \n", ret);
              }
              return 0;
}

三、 strerror

1.了解错误码的产生

使用库函数的时候
调用库函数失败时,都会生成错误码

全局错误码

int errno 
给错误码赋予 5 我们很难知道啥意思
这是就要用到我们的库函数 strerror函数
会将错误码翻译成对应信息
2.strerror 函数

原型

char * strerror ( int errnum );
可以看见 函数的参数就是 错误码

3.strerror函数的使用

// 函数的使用往往与打开文件 有关 现在只是演示 函数的使用
int main()
{
	printf("%s\n", strerror(0));
	printf("%s\n", strerror(1));
	printf("%s\n", strerror(2));
	printf("%s\n", strerror(3));
	printf("%s\n", strerror(5));
	
	return 0;
}

在这里插入图片描述

四、内存拷贝函数(memcpy)

1.函数原型

头文件<string.h>
void * memcpy ( void * destination, const void * source, size_t num );
destination 目的地     source  源头   num 拷贝多少字节的空间
函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
这个函数在遇到 '\0' 的时候并不会停下来。
如果source和destination有任何的重叠,复制的结果都是未定义的。

2.memcpy函数使用

#include<stdio.h>
#include<string.h>
int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	memcpy(arr2, arr1, 20);
	int i = 0;
	for (i = 0; i < 10;i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

3.memcpy函数的模拟实现

// memcpy 函数的使用
// 内存拷贝函数   --- 头文件
// #include <string.h>
//size_t 无符号整数
#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{
       void* ret = dest;
       assert(dest && src); // 断言防止 dest src 为空指针
       while (num--) // 先判断 20  不等于 0 然后 -- 等于 19进入循环
       {
              *(char*)dest = *(char*)src;
              dest = (char*)dest + 1;
              src = (char*)src + 1;
       }
       return ret;
}
int main()
{
       int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
       int arr2[10] = { 0 };
       //memcpy(arr2, arr1, 20);
       my_memcpy(arr2, arr1, 20);
       for (int i = 0; i < 5; i++)
       {
              printf("%d ", arr2[i]);
       }
       return 0;
}

五、memmove

1. 解决重叠问题

如果两 个数据 重叠
memmove 函数可以处理内存重叠 的情况
函数原型
void * memmove ( void * destination, const void * source, size_t num );
和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
如果源空间和目标空间出现重叠,就得使用memmove函数处理。

2.memmove 函数使用

#include<stdio.h>
#include<string.h>
#include<assert.h>


void* my_memcpy(void* dest, const void* stc, size_t num)
{
       void* ret = dest;
       assert(dest && stc);
       while (num--)
       {
              *(char*)dest = *(char*)stc;
              dest = (char*)dest + 1;
              stc = (char*)stc + 1;
       }
       return ret;
}
int main()
{
       int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
       int arr2[10] = { 0 };
       //memcpy(arr2, arr1, 20);
       //my_memcpy(arr1+2, arr1, 20);
       //调试后可以明显发现 我们 的 值被覆盖
       // 原本我们想 打印 的值 为
       // 1 2 1 2 3 4 5 8 9 10
       // 调试后 我们 得到的 是
       // 1 2 1 2 1 2 1 8 9 10  
       memmove(arr1 + 2, arr1, 20);
       return 0;
}

在这里插入图片描述
使用 memmove 函数 后
在这里插入图片描述
可以发现 通过 memmove 函数 解决了 数组 在内存中重叠 覆盖的问题

3.memmove模拟实现

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3 dest 与 str 不重叠时 不管 是 前 到 后 还是 后 到 前
其结果都是 一样
总结 如果 dest与 str 重叠 而且 dest 在 str 前面 则要用 前到后
反之 后 到 前

接下来用代码实现

#include<stdio.h>
#include<assert.h>
void* my_memmove(void* dest, void* stc, size_t num)
{
	assert(dest && stc);
	if (dest < stc)
	{
		//前--->后
		while (num--)
		{
			*(char*)dest = *(char*)stc;
			dest = (char*)dest + 1;
			stc = (char*)stc + 1;
		}
	}
	else
	{
		//后--->前
		while (num--)
		{
			*((char*)dest + num) = *((char*)stc + num);

		}
	}
}
int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr1 + 2, arr1, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

在这里插入图片描述

六、内存比较函数(memcmp)

1.初步了解memcmp 函数

原型 int memcmp ( const void * ptr1, const void * ptr2, size_t num );
与strcmp 差不多
大于 返回一个非零 的数
小于 返回 一个 负数
等于 发回 0
num 表示比较的字节

2.memcmp的使用

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abdfeg";
	int ret = memcmp(arr1, arr2, 3);
	if (ret > 0)
	{
		printf("arr1 > arr2");
	}
	else if (ret < 0)
	{
		printf("arr1 < arr2");
	}
	else
	{
		printf("arr1 == arr2 ");
	}
	return 0;
}

3.memcmp函数模拟实现

#include<stdio.h>
#include<string.h>
#include<assert.h>
int my_memcmp(const void* arr1, const void* arr2, size_t num)
{
	assert(arr1 && arr2);
	char* s1 = (char*)arr1;
	char* s2 = (char*)arr2;
	int ret = 0;
	while (num-- && !(ret = (*s1) - (*s2)))
	{
		s1++;
		s2++;
	}
	if (ret > 0)
	{
		return 1;
	}
	else if (ret < 0)
	{
		return -1;
	}
	return 0;
}
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abdfeg";
	int ret = my_memcmp(arr1, arr2, 3);
	if (ret > 0)
	{
		printf("arr1 > arr2");
	}
	else if (ret < 0)
	{
		printf("arr1 < arr2");
	}
	else
	{
		printf("arr1 == arr2 ");
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值