字符串逆序(不使用库函数并用递归实现)

news2024/12/23 16:38:59

文章目录

  • 前言
  • 一、题目要求
  • 二、解题步骤
    • 1.大概框架
    • 2.如何反向排列?
    • 3.模拟实现strlen
    • 4.实现反向排列
    • 5.递归实现反向排列
  • 总结


前言

嗨,亲爱的读者们!我是艾老虎尤,。今天,我们将带着好奇心,探索一个题目,这个题目对新手非常友好,。在这个题目中,我们将遇到各种编程元素,输入输出,条件语句,指针,循环,函数和递归,当然如果你是老手的话,也可以和我一起复习一下这些最基础的知识,话不多说,我们直接开始。


一、题目要求

编写一个函数 reverse_string(char * string)(递归实现)

实现: 将参数字符串中的字符反向排列,不是逆序打印。

要求: 不能使用C函数库中的字符串操作函数。

比如:

char arr[] = "abcdef";

逆序之后数组的内容变成:fedcba

二、解题步骤

1.大概框架

首先我们利用最基本的信息先把整个框架写出来,比如他要一个字符串,要一个函数,我们就可以先把这些和主函数写出来。

代码如下(示例):

#include<stdio.h>
//返回类型  函数名     函数体
void reverse_string(char* arr)
{

}

int main()
{
	char arr[] = "abcdef";//字符串
	reverse_string(arr);//定义的函数
	return 0;
}


数组名就是数组首元素的地址,是地址的话函数就要使用指针接收

2.如何反向排列?

首先我们设想一下,假设一个字符里面存储的是abcdef,咱们可以先调转af的位置,然后再调转be的位置,然后再调转cd的位置,用代码怎么实现呢?实际上很简单,a就是字符串第一个元素,f就是字符串里面最后一个元素,所以我们先要求出字符串的长度。


3.模拟实现strlen

我们都是到有一个库函数叫做strlen,它的逻辑就是求从第一个字符开始向后进行查找,直到遇到字符串的结束标志\0,就返回\0之前出现过字符的总和,就是求出字符串的长度,但是题目规定不能使用库函数,所以我们就模拟实现库函数。

代码如下(示例):

#include<stdio.h>
int my_strlen(char* arr)
{
	int count = 0;//计数器
	while (*arr != '\0')//如果这个元素不等于结束标志,进入循环
	{
		count++;//计数器自增1
		arr++;//找到下一个需要对比的元素
	}
	printf("字符串的长度是:%d\n", count);
	return count;
}

//返回类型  函数名     函数体
void reverse_string(char* arr)
{
	int len = my_strlen(arr);//自定义函数求字符串长度
}

int main()
{
	char arr[] = "abcdef";//字符串
	reverse_string(arr);//定义的函数
	return 0;
}

4.实现反向排列

当我们知道了字符串的长度之后,我们就定义两个变量,
一个叫left,对应的是我们第一个元素的位置
第二个叫right,对应的是我们最后一个元素的位置
当我们交换完一对元素后,让left向后移动一位,找到下一个元素,在让right向前移动一位,找到上一个元素,接下来我为大家画图展示。

在这里插入图片描述

上图我们发现,交换的过程是一个循环,而当right>left的时候,就证明元素全部交换完了,不需要再进行下去了,由此我们可以写出以下代码。

代码如下(示例):

#include<stdio.h>
int my_strlen(char* arr)
{
	int count = 0;//计数器
	while (*arr != '\0')//如果这个元素不等于结束标志,进入循环
	{
		count++;//计数器自增1
		arr++;//找到下一个需要对比的元素
	}
	printf("字符串的长度是:%d\n", count);
	return count;
}

//返回类型  函数名     函数体
void reverse_string(char *arr)
{
	int len = my_strlen(arr);//自定义函数求字符串长度
	int left = 0;
	int right = len - 1;
	while (right > left)
	{
		//交换两个元素
		char tmp = *(arr+left);
		*(arr + left) = *(arr+right);
		*(arr + right) = tmp;
		left++;
		right--;
	}
}

int main()
{
	char arr[] = "abcdef";//字符串
	reverse_string(arr);//定义的函数
	printf("%s", arr);
	return 0;
}

写到这里的时候,就已经可以实现反向排列了。

运行效果:
在这里插入图片描述

可是题目要求我们使用递归解决,于是我要改进一下代码,让代码符合题意。


5.递归实现反向排列

递归的两个必要条件
1.存在限制条件,当满足这个限制条件的时候,递归便不再继续。
2.每次递归调用之后越来越接近这个限制条件

之前我们的思路是把第一个元素放到倒数第一的位置上,把第二个元素放到倒数第二的位置上,以此内推,实际上我们也可以把问题看成,先交换第一个元素和最后一个元素,再递归第二个元素,以此内推,我还是画图为大家展示。

在这里插入图片描述

void reverse_string(char* arr)
{
	int len = my_strlen(arr);//自定义函数求字符串长度
	char tmp = *arr;
	*arr = *(arr + len - 1);
	*(arr + len - 1) = tmp;

	reverse_string(arr + 1);//递归从下一个元素开始

}

这里我们会发现第一个问题,就是当第一次交换完后,再进入reverse_string函数如果从下一个元素开始的话,递归就会混乱,我画图为大家展示。

在这里插入图片描述

想解决这个问题也不难,我们只需要改变语句的执行顺序,先把最后元素赋值成 \0,等递归结束再把a的值赋值给\0

void reverse_string(char* arr)
{
	int len = my_strlen(arr);//自定义函数求字符串长度
	char tmp = *arr;
	*arr = *(arr + len - 1);
	*(arr + len - 1) = '\0';

	reverse_string(arr + 1);

	*(arr + len - 1) = tmp;


}

最后我们给递归添加一个限制条件,不然的话他会一直递归下去,限制条件就是当递归里面的元素大于等于2时,才需要继续递归。

完整代码:

#include<stdio.h>
int my_strlen(char* arr)
{
	int count = 0;//计数器
	while (*arr != '\0')//如果这个元素不等于结束标志,进入循环
	{
		count++;//计数器自增1
		arr++;//找到下一个需要对比的元素
	}
	printf("字符串的长度是:%d\n", count);
	return count;
}

//返回类型  函数名     函数体
void reverse_string(char* arr)
{
	int len = my_strlen(arr);//自定义函数求字符串长度
	char tmp = *arr;
	*arr = *(arr + len - 1);
	*(arr + len - 1) = '\0';
	if(my_strlen(arr+1)>=2)
		reverse_string(arr + 1);

	*(arr + len - 1) = tmp;


}

int main()
{
	char arr[] = "abcdef";//字符串
	reverse_string(arr);//定义的函数
	printf("%s", arr);
	return 0;
}

效果展示:
在这里插入图片描述


总结

在本篇博客中,我们讨论了如何使用递归的方式来实现字符串的逆序。通过不使用库函数,我们需要仅仅使用递归来实现这一功能。

首先,我们讨论了递归的基本概念和原理,指出了使用递归的条件:问题可以被分解为较小的子问题,并且每个子问题可以通过调用相同的函数来解决。然后,我们通过编写一个递归函数来实现字符串的逆序。

在实现递归函数时,,我们使用递归的方式,将字符串的第一个字符与最后一个字符进行交换,从而实现字符串的逆序。我们将交换后的字符串作为一个新的问题传递给递归函数,直到递归到边界条件,逆序的字符串最后返回。

最后,我们给出了逆序字符串的示例代码,并通过测试验证了递归函数的正确性。

通过本篇博客的学习,我们深入理解了递归的原理和应用,掌握了使用递归函数来实现字符串逆序的方法。递归函数的实现过程相对简单,但需要注意边界条件的处理和递归调用的方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/994629.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

显示器鼠标滚动时或者拖拽文字变为绿色

新电脑&#xff0c;新显示器&#xff0c;看文章时滚动鼠标滑轮&#xff0c;文字颜色就变为绿色。 拖住文本文档或者浏览器等有文字的窗口&#xff0c;文字也会变为绿色。 静止时一点儿问题没有。 以下视频展示滚动和拖拽的操作&#xff0c;视频看不出变色&#xff0c;只参考…

TuyaOS开发学习笔记(2)——NB-IoT开发SDK架构、运行流程

一、SDK架构 1.1 架构框图 基于 TuyaOS 系统&#xff0c;可以裁剪得到的适用于 NB-IoT 协议产品接入的 SDK。SDK 将设备配网、上下行数据通信、产测授权、固件 OTA 升级等接口进行封装&#xff0c;并提供相关函数。 1.2 目录结构 1.2.1 TuyaOS目录说明 adapter&#xff1a;T…

transformer 总结(超详细-初版)

相关知识链接 attention1attention2 引言 本文主要详解 transformer 的算法结构以及理论解释&#xff0c;代码实现以及具体实现时候的细节放在下一篇来详述。 下面就通过上图中 transformer 的结构来依次解析 输入部分(Encode 侧) input 输出主要包含 两个部分&#xff1a…

[acwing周赛复盘] 第 120 场周赛20230909

[acwing周赛复盘] 第 120 场周赛20230909 总结5146. 最大GCD1. 题目描述2. 思路分析3. 代码实现 5147. 数量1. 题目描述2. 思路分析3. 代码实现 5148. 字符串匹配1. 题目描述2. 思路分析3. 代码实现 六、参考链接 总结 T1好难啊。T1 数学T2 dfs/数位dpT3 计数贪心 5146. 最大…

第51节:cesium 范围查询(含源码+视频)

结果示例: 完整源码: <template><div class="viewer"><el-button-group class="top_item"><el-button type=

render和jsx

render和jsx 1..vue文件最后会变成一个对象。 一个vue文件要么是render写法&#xff0c;要么是模板写法。 为什么React在大型项目中比较适合&#xff1f; 在大型项目中比较适合&#xff1f; 因为React使用jsx&#xff0c;比较灵活。

ISYSTEM调试实践11-Profiler Timeline和软件运行时间分析

一 前言 本文主要内容是讨论嵌入式软件的时间分析&#xff0c;供大家探讨&#xff0c;如果有疑问欢迎探讨。 对于汽车软件&#xff0c;往往对执行的时序和代码运行的时间有着严格要求。对于在主循环内执行的任务函数&#xff0c;不论是手写还是Autosar生成,能否节拍执行到&…

flink时间处理语义

背景 在flink中有两种不同的时间处理语义&#xff0c;一种是基于算子处理时间的时间&#xff0c;也就是以flink的算子所在的机器的本地时间为准&#xff0c;一种是事件发生的实际时间&#xff0c;它只与事件发生时的时间有关&#xff0c;而与flink算子的所在的本地机器的本地时…

利用grafana展示Zabbix数据可视化

导入zabbix数据源&#xff0c;可以直接创建图形了。 单击“”按钮&#xff0c;选择创建仪表盘&#xff0c;单击要创建的图形&#xff0c;图形种类有很多&#xff0c;常用的有图表&#xff0c;列表&#xff0c;报警清单&#xff0c;zabbix触发器&#xff0c;文本。 创建巡检图形…

C++ 多线程 学习笔记

线程睡眠很稳定&#xff0c;但无线程睡眠不稳定 线程调用类方法&#xff1a; 有参数时调用方法&#xff1a; 当参数为引用时&#xff1a; 当同一资源被多个线程同时引用时&#xff0c;为防止资源抢占&#xff0c;使用mutex&#xff0c;互斥锁 头文件#include "mutex"…

蓝桥杯官网练习题(纸牌三角形)

题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 A,2,3,4,5,6,7,8,9 共 99 张纸牌排成一个正三角形&#xff08;A 按 1 计算&#xff09;。要求每个边的和相等。 下图就是一种排法。 这样的排法可能会有很多。 如果…

thinkphp6-简简单单地开发接口

目录 1.前言TP6简介 2.项目目录3.运行项目运行命令访问规则 4.model db使用db连接配置model编写及调用调用接口 5.返回json格式 1.前言 基于上篇文章环境搭建后&#xff0c;便开始简单学习上手开发接口…记录重要的过程&#xff01; Windows-试用phpthink发现原来可这样快速搭…

Spring Data JPA:简化数据库交互的艺术

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

Jmeter 实现 mqtt 协议压力测试

1. 下载jmeter&#xff0c;解压 https://jmeter.apache.org/download_jmeter.cgi 以 5.4.3 为例&#xff0c;下载地址&#xff1a; https://dlcdn.apache.org//jmeter/binaries/apache-jmeter-5.4.3.zip linux下解压&#xff1a; unzip apache-jmeter-5.4.3.zip 2. 下载m…

六)Stable Diffussion使用教程:图生图SD Upscale

这一篇说说SD放大(SD Upscale)。 图生图是没有 “高清修复” 选项的,因为从文生图的高清修复原理来看,图生图本身就是高清修复:只需要在重绘目标图像时,等比例增大图像的分辨率就可以了。 这里我们通过图库浏览器浏览一张图片,然后点击图生图,图片的所有出图参数就会…

运维学习之采集器 node_exporter 1.3.1安装并使用

参考《监控系统部署prometheus基本功能》先完成prometheus部署。 wget https://github.com/prometheus/node_exporter/releases/download/v1.3.1/node_exporter-1.3.1.linux-amd64.tar.gz下载压缩包。 tar -zxf node_exporter-1.3.1.linux-amd64.tar.gz进行解压。 cp node_e…

安全实战 | 怎么用零信任防范弱密码?

防范弱密码&#xff0c;不仅需要提升安全性&#xff0c;更需要提升用户体验。 比如在登录各类业务系统时&#xff0c;我们希望员工登录不同系统不再频繁切换账号密码&#xff0c;不再需要3-5个月更换一次密码&#xff0c;也不再需要频繁的输入、记录、找回密码。 员工所有的办…

Spring Boot与Kubernetes:现代云部署的完美组合

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

第六章 图 四、图的广度优先遍历(BFS算法、广度优先生成树、广度优先生成森林)

一、实现步骤 广度优先遍历的实现步骤如下&#xff1a; 1.从图的某一个节点开始&#xff0c;将该节点标记为已经访问过的节点。 2.将该节点加入到队列中。 3.当队列非空时&#xff0c;执行以下操作&#xff1a; a. 取出队列队首节点&#xff0c;并遍历该节点与之相邻的所有…

Spring AOP:面向切面编程在实际项目中的应用

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…