用递归实现字符串逆序(不使用库函数)
文章目录
- 前言
- 一、题目要求
- 二、解题步骤
- 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,咱们可以先调转
a和f的位置,然后再调转b和e的位置,然后再调转c和d的位置,用代码怎么实现呢?实际上很简单,a就是字符串第一个元素,f就是字符串里面最后一个元素,所以我们先要求出字符串的长度。
3.模拟实现strlen
我们都是到有一个库函数叫做strlen,它的逻辑就是求从第一个字符开始向后进行查找,直到遇到字符串的结束标志
\0,就返回\0之前出现过字符的总和,就是求出字符串的长度,但是题目规定不能使用库函数,所以我们就模拟实现库函数。
代码如下(示例):
#include<stdio.h>
int my_strlen(char* arr)
{int count = 0;//计数器while (*arr != '\0')//如果这个元素不等于结束标志,进入循环{count++;//计数器自增1arr++;//找到下一个需要对比的元素}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++;//计数器自增1arr++;//找到下一个需要对比的元素}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++;//计数器自增1arr++;//找到下一个需要对比的元素}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;
}
效果展示:

总结
在本篇博客中,我们讨论了如何使用递归的方式来实现字符串的逆序。通过不使用库函数,我们需要仅仅使用递归来实现这一功能。
首先,我们讨论了递归的基本概念和原理,指出了使用递归的条件:问题可以被分解为较小的子问题,并且每个子问题可以通过调用相同的函数来解决。然后,我们通过编写一个递归函数来实现字符串的逆序。
在实现递归函数时,,我们使用递归的方式,将字符串的第一个字符与最后一个字符进行交换,从而实现字符串的逆序。我们将交换后的字符串作为一个新的问题传递给递归函数,直到递归到边界条件,逆序的字符串最后返回。
最后,我们给出了逆序字符串的示例代码,并通过测试验证了递归函数的正确性。
通过本篇博客的学习,我们深入理解了递归的原理和应用,掌握了使用递归函数来实现字符串逆序的方法。递归函数的实现过程相对简单,但需要注意边界条件的处理和递归调用的方式。
相关文章:
用递归实现字符串逆序(不使用库函数)
文章目录 前言一、题目要求二、解题步骤1.大概框架2.如何反向排列?3.模拟实现strlen4.实现反向排列5.递归实现反向排列 总结 前言 嗨,亲爱的读者们!我是艾老虎尤,今天,我们将探索一个题目,这个题目对新手非…...
初学python(一)
一、python的背景和前景 二、 python的一些小事项 1、在Java、C中,2 / 3 0,也就是整数 / 整数 整数,会把小数部分舍掉。而在python中2 / 3 0.66666.... 不会舍掉小数部分。 在编程语言中,浮点数遵循IEEE754标准,不…...
Excel VSTO开发8 -相关控件
版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 8 相关控件 在VSTO开发中,Ribbon(或称为Ribbon UI)是指Office应用程序中的那个位于顶部的带有选…...
华为数据管理——《华为数据之道》
数据分析与开发 元数据是描述数据的数据,用于打破业务和IT之间的语言障碍,帮助业务更好地理解数据。 元数据是数据中台的重要的基础设施,元数据治理贯彻数据产生、加工、消费的全过程,沉淀了数据资产,搭建了技术和业务…...
Flink CDC 菜鸟教程 -环境篇
本教程将介绍如何使用 Flink CDC 来实现这个需求, 在 Flink SQL CLI 中进行,只涉及 SQL,无需一行 Java/Scala 代码,也无需安装 IDE。 系统的整体架构如下图所示: 环境篇 1、 准备一台Linux 2、准备教程所需要的组件 下载 flink-1.13.2 并将其解压至目录 flink-1.13.2 …...
【线上问题】linux部署docker应用docker-compose启动报端口占用问题(感觉上没有被占用)
目录 一、问题说明二、排查过程 一、问题说明 1.linux服务器使用的不是root用户权限 2.docker应用服务没有关闭的情况下,做了些重装docker,重启docker等操作 3.docker-compose up -d然后docker logs查看日志报端口被占用 4.netstat -ntpl | grep 端口 也…...
解决虚拟机克隆后IP和命名冲突问题
目录 解决IP冲突问题 解决命名冲突 解决IP冲突问题 克隆后的虚拟机和硬件地址和ip和我们原虚拟机的相同,我们需要重新生成硬件地址和定义ip,步骤如下: (1)进入 /etc/sysconfig/network-scripts/ifcfg-ens33 配置文件…...
分享一个python基于数据可视化的智慧社区服务平台源码
💕💕作者:计算机源码社 💕💕个人简介:本人七年开发经验,擅长Java、Python、PHP、.NET、Node.js、微信小程序、爬虫、大数据等,大家有这一块的问题可以一起交流! …...
[密码学入门]凯撒密码
单表代换 单表:英文26字母的顺序 代换:替换为别的字母并保证解密的唯一性 假如我们让加密方式为所有字母顺序移动3位 import stringstring.ascii_lowercase abcdefghijklmnopqrstuvwxyz b3 加密算法y(xb)mod26 解密算法为x(y-b)mod26 密钥空间26 …...
博客之QQ登录功能(一)
流程图 上图spring social 封装了1-8步需要的工作 1、新建包和书写配置文件 public class QQProperties {//App唯一标 识private String appId "100550231";private String appSecret "69b6ab57b22f3c2fe6a6149274e3295e";//QQ供应商private String…...
Redis多机数据库实现
Redis多机数据库实现 为《Redis设计与实现》笔记 复制 客户端可以使用SLAVEOF命令将指定服务器设置为该服务器的主服务器 127.0.0.1:12345> SLAVEOF 127.0.0.1 6379127.0.0.1:6379将被设置为127.0.0.1:123456的主服务器 旧版复制功能的实现 Redis的复制功能分为同步&a…...
Leangoo领歌 -敏捷任务管理软件,任务管理更轻松更透明
任务管理,简单易懂,就是对任务进行管理。那怎么可以更好进行任务管理呢?怎么样样可以让任务进度可视化,一目了然呢?有效的管理可以让我们事半功倍。 接下来我们看一下如何借助任务管理软件高效的做任务管理。 首先…...
go的iris框架进行本地资源映射到服务端
我这里使用的是HandleDirapi,有其他的请补充 package mainimport ("github.com/kataras/iris/v12" )type Hello struct{Status int json:"status"Message string json:"message" }func main(){app : iris.New()//第一个api:相当于首页app.Get(&q…...
代码随想录day46|139. 单词拆分
139. 单词拆分 class Solution:def wordBreak(self, s: str, wordDict: List[str]) -> bool:dp [False]*(len(s)1)dp[0]Truefor i in range(len(s)1):for j in wordDict:if i>len(j) and (s[i-len(j):i] in wordDict) and dp[i-len(j)]:dp[i] Truereturn dp[len(s)]多…...
MATLAB实现函数拟合
目录 一.理论知识 1.拟合与插值的区别 2.几何意义 3.误差分析 二.操作实现 1.数据准备 2.使用cftool——拟合工具箱 三.函数拟合典例 四.代码扩展 一.理论知识 1.拟合与插值的区别 通俗的说,插值的本质是根据现有离散点的信息创建出更多的离散点…...
vue优化首屏加载时间优化-cdn引入第三方包
前言 为什么要进行首屏加载优化,因为随着我们静态资源和第三方包和代码增加,压缩之后包会越来越大 随着网络的影响,在我们第一输入url请求资源时候,网络阻塞,加载时间长,用户体验不好 仔细观察后就会发现…...
lv4 嵌入式开发-3 标准IO的读写
目录 1 标准I/O – 读写流 2 标准I/O – 按字符输入 3 标准I/O – 按字符输出 4 标准I/O – 思考和练习 5 标准I/O – 按行输入 6 标准I/O – 按行输出 7 标准I/O – 思考和练习 1 标准I/O – 读写流 流支持不同的读写方式: 读写一个字符:fgetc()/fputc()一…...
iOS UIDevice设备信息
识别设备和操作系统 //获得共享设备实例 open class var current: UIDevice { get }//识别设备的名称 open var name: String { get } // e.g. "My iPhone"//设备类型 open var model: String { get } // e.g. "iPhone", "iPod touch"//本地化设…...
SLAM ORB-SLAM2(2)编译安装
SLAM ORB-SLAM2(2)编译安装 1. 软件包依赖安装2. 依赖安装2.1. Eigen2.2. Pangolin2.3. OpenCV3. ORB-SLAM23.1. 源码下载3.2. 文件修改3.3. 扩大交换空间3.4. 编译1. 软件包依赖安装 以一个纯净的ubuntu20.04桌面版为例 1.首先设置软件源为清华源 2.安装必要依赖 sudo ap…...
第11节-PhotoShop基础课程-索套工具
文章目录 前言1.索套工具 选中后按Ctrl 可以移动2.加,减,交叉 shift alt 2.多边形索套工具 手动首尾相连 或者双击空地1.单击绘制直线选区2.双击结束绘制3.加,减,交叉4. delete可以删除节点 3.磁性索套工具1.沿着边缘自动吸附2.可…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...
MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...
stm32wle5 lpuart DMA数据不接收
配置波特率9600时,需要使用外部低速晶振...
