学C的第二十九天【字符串函数和内存函数的介绍(二)】

这篇具有很好参考价值的文章主要介绍了学C的第二十九天【字符串函数和内存函数的介绍(二)】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

=========================================================================

相关代码gitee自取

C语言学习日记: 加油努力 (gitee.com)

 =========================================================================

接上期

学C的第二十八天【字符串函数和内存函数的介绍(一)】_高高的胖子的博客-CSDN博客

 =========================================================================

                        

1 . 函数介绍(续)

(11). memcpy()函数:

从存储区 str2 拷贝n 个字节的数据到存储区 str1

               

函数返回值类型和相关参数:

             

void * memcpy ( void * destination, const void * source, size_t num );

               

(参数接收 任意类型的目标空间地址 任意类型的常量源数据地址拷贝的字节数

返回 任意类型的拷贝完成后的目标空间地址

学C的第二十九天【字符串函数和内存函数的介绍(二)】,CCC全是C,c语言,c++

                    

注意事项:

(1).

函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置

需要头文件<string.h>

                  

(2).

这个函数在遇到 '\0' 的时候并不会停下来

                

(3).

如果sourcedestination有任何的重叠复制的结果都是未定义的

               

(4).

学会memcpy函数的模拟实现下面第2个模块有

                     


                    

(12). memmove()函数:

从存储区 str2 移动 n 个字节的数据到存储区 str1

                

函数返回值类型和相关参数:

             

void * memmove ( void * destination, const void * source, size_t num );

               

(参数接收 任意类型的目标空间地址 任意类型的常量源数据地址移动的字节数

返回 任意类型的移动完成后的目标空间地址

学C的第二十九天【字符串函数和内存函数的介绍(二)】,CCC全是C,c语言,c++

                    

注意事项:

(1).

和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠

                  

(2).

如果源空间目标空间出现重叠,就得使用memmove函数处理

                

(3).

学会memmove函数的模拟实现下面第2个模块有

                     


                    

(13). memcmp()函数:

比较从ptr1和ptr2指针开始的num个字节

            

函数返回值类型和相关参数:

             

int memcmp ( const void * ptr1, const void * ptr2, size_t num );

                    

(参数接收 两个任意类型的常量地址 比较的字节数

返回 一个整数

学C的第二十九天【字符串函数和内存函数的介绍(二)】,CCC全是C,c语言,c++

                    

注意事项:

(1). 标准规定:

                   

第一个元素 大于 第二个元素,则返回 大于0 的数字

             

第一个元素 等于 第二个元素,则 返回0

                         

第一个元素 小于 第二个元素,则返回 小于0 的数字

         

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

             

2 . 库函数的模拟实现(续)

(6). 模拟实现memcpy()函数:

模拟实现的自定义函数:

学C的第二十九天【字符串函数和内存函数的介绍(二)】,CCC全是C,c语言,c++

                  

主函数:

学C的第二十九天【字符串函数和内存函数的介绍(二)】,CCC全是C,c语言,c++

                       

对应代码:

//模拟memcpy()函数:
#include <stdio.h>
#include <assert.h>

void* my_memcpy(void* dest, const void* src, size_t num)
//返回值为 拷贝结束后的目标空间起始地址
//size_t num:参数接收的是 要拷贝的字节数,因为不同类型的数据字节数是不同的
{
	//保存目标空间的原始地址,方便拷贝完后返回原地址:
	void* ret = dest;

	//使用断言,确保两指针不是空指针:
	assert(dest && src);

	while (num--)
	//将两个void*指针,转化为char*指针,一个字节一个字节拷贝
	//所以有几个字节就拷贝几次
	{
		//转化为char*指针,一个字节一个字节拷贝:
		//强制类型转化只是临时的:
		*(char*)dest = *(char*)src;

		//移动指针拷贝下一位:
		//因为void*指针不能++和*,
		//所以要转化为char*后+1再赋给dest:
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}

	//返回原地址:
	return ret;
}

int main()
{
	//源数据:
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	//目标空间:
	int arr2[20] = { 0 };

	//将arr1的内容拷贝到arr2中,因为是int类型不能使用strcpy函数:
	//使用模拟的自定义函数:
	my_memcpy(arr2, arr1, 20);

	//结果:
	int i = 0;
	for (i = 0; i < 20; i++)
	{
		printf("%d ", arr2[i]);
	}

	return 0;
}

                     


                    

(7). 模拟实现memmove()函数:

模拟实现的自定义函数:

学C的第二十九天【字符串函数和内存函数的介绍(二)】,CCC全是C,c语言,c++

                  

主函数:

学C的第二十九天【字符串函数和内存函数的介绍(二)】,CCC全是C,c语言,c++

                  

对应代码:

//模拟实现memmove函数:
#include <stdio.h>
#include <assert.h>

void* my_memmove(void* dest, const void* src, size_t num)
//				  目标空间		原数据空间    (首元素地址)
{
	//保存起始位置:
	void* ret = dest;

	//断言:
	assert(dest && src);

	//如果源数据空间在目标空间有重叠,则有2种情况:
	//1. 目标空间首地址(dest) 在 源数据空间首地址左边(src) ,
	//   那就需要 从前往后 进行移动,才不会有源数据被覆盖的情况
	//2. 目标空间首地址(dest) 在 源数据空间首地址右边(src) ,
	//   那就需要 从后往前 进行移动,才不会有源数据被覆盖的情况
	//如果两个空间没有重叠的情况,则 从前往后 还是 从后往前 移动都可以
	//使用分两种情况即可:
	//void* 不能解引用和+1-1操作,但可以比(地址)大小
	if (dest < src) //第一种情况
	{
		//从前往后 移动:
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else //第二种情况
	{
		//从后往前 移动:
		while (num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}

	return ret;
}

int main()
{
	//源数据:
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };

	my_memmove(arr1, arr1+2, 20);

	//结果:
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}

	return 0;
}

                   

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                     

3 . 练习

(1). 杨氏矩阵:

          

题目:

有一个数字矩阵二维数组),

矩阵的每行从左到右是递增的
矩阵从上到下是递增的
请编写程序在这样的矩阵中查找某个数字是否存在,

要求:时间复杂度小于O(N)

                     

时间复杂度为O(N)的版本:

学C的第二十九天【字符串函数和内存函数的介绍(二)】,CCC全是C,c语言,c++

        

对应代码:
//正常写法,时间复杂度为O(N):
#include <stdio.h>
int main()
{
	//给出符合杨氏矩阵的二维数组:
	int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };

	//输入要找的数:
	int k = 0;
	scanf("%d", &k);

	//在二维数组中一个一个遍历:时间复杂度为O(N)
	int i = 0; 
	for (i = 0; i < 3; i++)//遍历行
	{
		int j = 0;
		for (j = 0; j < 3; j++)//遍历列
		{
			if (arr[i][j] == k)//如果找到了
			{
				//进行打印:
				printf("找到了,它的下标为:%d %d", i, j);
				
				return 0; 
				//直接使用return结束程序,
				//break只能跳出一层循环
			}
		}
	}

	//未找到则打印未找到:
	printf("未找到");

	return 0;
}

            

时间复杂度小于O(N)的版本:

学C的第二十九天【字符串函数和内存函数的介绍(二)】,CCC全是C,c语言,c++

                    

对应代码:
#include <stdio.h>

void young_tableau_search(int arr[3][3], int k, int* px, int* py)
{
	//开始查找,思路:
	//因为是杨氏矩阵,所以一行中最右边的数是最大的
	//这个最大值如果比要找的值都小的话,那就可以排除这一行
	//列也是同理

	// 坐标(0,2),第一行的最大值
	int x = 0; //二维数组的行
	int y = *py-1; //二维数组的列
	while (x <= *px-1 && y >= 0)
		//行最大调整到第二行,列最多调整到第0行
	{
		if (arr[x][y] < k)
			//如果第一行的最大值都小于k,
		{
			x++; //排除这一行,移到下一行
		}
		else if (arr[x][y] > k)
			//如果第一行的最大值大于k,
		{
			y--; //说明k可能就在这一行,移动列进行查找
		}
		else
		{
			//找到了就把k的行和列赋给指针px和指针py:
			*px = x;
			*py = y;
			return;
		}
	}

	//自定义未找到的情况:
	*px = -1;
	*py = -1;
}

int main()
{
	//给出符合杨氏矩阵的二维数组:
	int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
	//		1 2 3
	//		4 5 6
	//		7 8 9

	//输入要找的数:
	int k = 0;
	scanf("%d", &k);

	int x = 3; //k的行
	int y = 3; //k的列

	//自定义一个函数进行查找:
	young_tableau_search(arr, k, &x, &y);
	//参数:	二维数组名,要找的值,行数,列数

	//通过函数的使用情况打印相应情况:
	if (x==-1 && y==-1)
		//未找到:
	{
		printf("未找到");
	}
	else
		//找到了:
	{
		printf("找到了,它的下标为:第%d行 第%d列", x, y);
	}

	return 0;
}

                     


                    

(2). 字符串左旋:

          

题目:

实现一个函数,可以左旋字符串中的k个字符

         
例如:
ABCD左旋一个字符得到BCDA
ABCD左旋两个字符得到CDAB

             

方法1:左旋一个字符就移动一次剩余的字符

学C的第二十九天【字符串函数和内存函数的介绍(二)】,CCC全是C,c语言,c++

                 

对应代码:
//方法1:左旋一个字符就移动一次剩余的字符
//实现一个函数,可以左旋字符串中的k个字符。
//例如:
//ABCD左旋一个字符得到BCDA
//ABCD左旋两个字符得到CDAB
#include <stdio.h>
#include <string.h>
#include <assert.h>

void left_move(char* str, int k)
{
	//断言:str不为空指针
	assert(str);

	//左旋k次:
	int j = 0;
	for (j = 0; j < k; j++)
	{
		//存放被左旋字符的地址,从第一个字符开始
		char tmp = *str;

		//求字符串长度:
		int len = strlen(str);

		//左旋后一个字符后,后面len-1个字符要往前挪一位
		int i = 0;
		for (i = 0; i < len - 1; i++)
		{
			//把后一个字符赋给前一个
			*(str + i) = *(str + i + 1);
			//这里就覆盖掉了前面一个字符,末尾空出一个字符
		}

		//将左旋的字符移动到尾部
		*(str + len - 1) = tmp;
	}
}

int main()
{
	char arr[] = "ABCD";

	//输入左旋次数:
	int k = 0;
	scanf("%d", &k);

	//使用自定义函数进行左旋:
	left_move(arr, k);
	//参数: 字符串首地址,左旋次数
	
	//打印左旋后结果:
	printf("%s\n", arr);

	return 0;
}

                    

方法2:

把字符串分为两部分,左旋字符为一部分,剩余字符为一部分,分别进行逆序,再整体逆序

学C的第二十九天【字符串函数和内存函数的介绍(二)】,CCC全是C,c语言,c++

                   文章来源地址https://www.toymoban.com/news/detail-598436.html

对应代码:
//方法2:
#include <stdio.h>
#include <assert.h>
#include <string.h>

//定义一个逆序函数:
void reverse(char* left, char* right)
{
	//断言:两指针不为空
	assert(left && right);

	//进行逆序:
	while (left < right)
		//两指针中间还有数就继续
	{
		char tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}
}

void left_move(char* str, int k)
{
	int len = strlen(str);

	k %= len;//防止重复操作

	//求左旋字符进行逆序:
	reverse(str, str + k - 1);

	//对剩余字符进行逆序:
	reverse(str + k, str + len - 1);

	//整体逆序:
	reverse(str, str + len - 1);
}

int main()
{
	char arr[] = "ABCD";
	
	//输入左旋次数:
	int k = 0;
	scanf("%d", &k);

	//使用自定义函数进行左旋:
	left_move(arr, k);
	//参数: 字符串首地址,左旋次数
	
	//打印左旋后结果:
	printf("%s\n", arr);

	return 0;
}

              

(3). 字符串旋转结果:

          

题目:

写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串

              

例如:

给定s1 =AABCDs2 = BCDAA返回1

给定s1=abcds2=ACBD返回0.

            

AABCD左旋一个字符得到ABCDA

AABCD左旋两个字符得到BCDAA

AABCD右旋一个字符得到DAABC

             

方法1:

str1每旋转一次就和str2进行对比,不同则继续进行下次旋转

学C的第二十九天【字符串函数和内存函数的介绍(二)】,CCC全是C,c语言,c++

                   

对应代码:
#include <stdio.h>
#include <string.h>
int is_left_move(char* str1, char* str2)
{
	//求字符串长度:
	int len = strlen(str1);

	int j = 0;
	for (j = 0; j < len; j++)
		//字符串长度为几,最多就旋转几次
	{
		//存放被左旋字符的地址,从第一个字符开始
		char tmp = *str1;

		//左旋后一个字符后,后面len-1个字符要往前挪一位
		int i = 0;
		for (i = 0; i < len - 1; i++)
		{
			//把后一个字符赋给前一个
			*(str1 + i) = *(str1 + i + 1);
			//这里就覆盖掉了前面一个字符,末尾空出一个字符
		}

		//将左旋的字符移动到尾部
		*(str1 + len - 1) = tmp;

		//到这里就旋转了1次,
		//每旋转1次就使用strcmp判断是否和str2相同:
		if (strcmp(str1, str2) == 0)
		{
			return 1;//找到返回1
		}
	}

	//未找到就返回0
	return 0;
}

int main()
{
	char arr1[] = "ABCDEF";
	char arr2[] = "CDEFAB";

	//使用自定义函数:
	int ret = is_left_move(arr1, arr2);

	//根据自定义函数返回结果进行打印:
	if (ret == 1)
	{
		printf("Yes\n");
	}
	else
	{
		printf("No\n");
	}

	return 0;
}

              

方法2:

把str1变成 “str1+str1”,如果 “str1+str1” 中有str2,那就可以通过str1旋转得到str2

学C的第二十九天【字符串函数和内存函数的介绍(二)】,CCC全是C,c语言,c++

                   

对应代码:
#include <stdio.h>
#include <string.h>
int is_left_move(char* str1, char* str2)
{
	int len1 = strlen(str1);
	int len2 = strlen(str2);

	//判断两字符串长度是否相同,不同的话肯定不能通过旋转得到:
	if (len1 != len2)
	{
		return 0;
	}

	//通过strncat在str1上再追加str1:
	strncat(str1, str1, len1);

	//判断追加后的str1中有没有str2,有则可以通过旋转得到:
	if (strstr(str1, str2) == NULL)
	{
		return 0;
	}
	else
	{
		return 1;
	}
}

int main()
{
	char arr1[20] = "ABCDEF";
	char arr2[] = "CDEFAB";

	//使用自定义函数:
	int ret = is_left_move(arr1, arr2);

	//根据自定义函数返回结果进行打印:
	if (ret == 1)
	{
		printf("Yes\n");
	}
	else
	{
		printf("No\n");
	}

	return 0;
}

到了这里,关于学C的第二十九天【字符串函数和内存函数的介绍(二)】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C语言】字符函数,字符串函数,内存函数

    大家好!今天我们来学习C语言中的字符函数,字符串函数和内存函数。 目录 1. 字符函数 1.1 字符分类函数 1.2 字符转换函数 1.2.1 tolower(将大写字母转化为小写字母) 1.2.2 toupper(将小写字母转化为大写字母) 2. 字符串函数 2.1 字符串输入函数 2.1.1 gets() ​2.1.2 fgets() 2.2 字符串

    2024年02月10日
    浏览(46)
  • 字符串函数+内存函数(详解)

    本期带大家一起来学习字符串函数+内存函数😀 😃 😄 1. 求字符串长度 strlen🚀🚀 字符串 已经 ‘\\0’ 作为结束标志 ,strlen函数返回的是在字符串中 ‘\\0’ 前面出现的字符个数(不包含 ‘\\0’ )。 strlen在库里面的参数是如此的 ⌛️⌛️ 接下来我们来模拟实现strlen ,接下来

    2023年04月17日
    浏览(33)
  • 字符串函数和内存操作函数

    目录 0.字符串回顾 1.函数介绍 1.1 strlen 1.2 strcpy 1.3 strcat 1.4 strcmp 1.5 strncpy 1.6 strncat 1.7 strncmp 1.8 strstr 1.9 strtok 1.10 strerror 1.11 memcpy 1.12 memmove 1.13 memcmp 1.14 memset 1.15 字符相关函数 字符分类函数 字符转换函数 2.函数模拟实现 2.1模拟实现strlen 2.2模拟实现strcpy 2.3模拟实现strcat 2.4模拟

    2024年02月15日
    浏览(96)
  • 字符串函数和内存函数详解(2)

    🐵本文会将会对剩余的 字符串库函数 和 内存函数 进行讲解 strstr函数原型: strstr用于在字符串中找子串,strstr会返回str1中出现str2的起始地址,如果在str1中没有找到str2,则返回空指针 strstr会返回arr1中第一次出现arr2的地址,这里就是\\\'l\\\'的地址,将其传给指针ret,在打印时

    2024年02月07日
    浏览(29)
  • 字符串和内存函数(2)

    2.13 memcpy void* memcpy(void* destination, const void* source, size_t num); 函数memcpy从source的位置开始向后复制num个 字节 的数据到destination的内存位置。 这个函数在遇到 ‘\\0’ 的时候并不会停下来。 如果source和destination有任何的重叠,复制的结果都是未定义的。 memcpy是内存拷贝,它可以拷

    2024年02月04日
    浏览(29)
  • <C语言> 字符串内存函数

    C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串 或者 字符数组 中。 字符串常量 适用于那些对它不做修改的字符串函数. 注意:字符串函数都需要包含头文件string.h strlen() 函数用于计算字符串的长度,即字符串中字符

    2024年02月15日
    浏览(33)
  • 【C】字符串函数和内存函数的介绍

    strlen size_t strlen ( const char * str ); 字符串已经 ‘\\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\\0’ 前面出现的字符个数(不包含 ‘\\0’ )。 参数指向的字符串必须要以 ‘\\0’ 结束。 注意函数的返回值为size_t,是无符号的( 易错 ) 代码演示: 运行结果: strcpy char* s

    2024年02月16日
    浏览(30)
  • c语言——字符串函数和内存操作函数

    包含在string.h头文件里 功能:返回字符串中有效字符的个数,遇到‘\\0’结束,不包括结束符‘\\0’. 函数的参数为------const char* str:字符指针 返回值的类型------size_t:无符号整数(即:unsigned int) 模拟实现strlen: 方法一:计数器的方法 方法二:不能创建临时变量的计数器

    2024年02月14日
    浏览(59)
  • C/C++字符函数和字符串函数详解————内存函数详解与模拟

    个人主页:点我进入主页 专栏分类:C语言初阶      C语言程序设计————KTV       C语言小游戏     C语言进阶 C语言刷题 欢迎大家点赞,评论,收藏。 一起努力,一起奔赴大厂。 目录 1.前言 2 .memcpy函数 3.memmove函数 4.memset函数  5.memcmp函数            前面学习了关

    2024年02月08日
    浏览(34)
  • C语言进阶---字符串+内存函数

    重点介绍处理字符和字符串的库函数的使用和注意事项。 求字符串长度 strlen() 长度不受限制的的字符串函数 strcpy() strcat() strcmp() 长度受限制的的字符串函数 strncpy() strncat() strncmp() 字符串查找 strstr() strtok() 错误信息报告 strerror() 字符操作 内存操作函数 memcpy() memmove() memset(

    2024年02月12日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包