本文近三千字,如有时间还请耐心看完,作者也是抱着学习的态度整理和总结的,仔细研究后对代码能力提高很有帮助,如有错误还请各位指出,也欢迎各位提供更好的解决思路。✊
目录
问题描述
编写一个函数Reverse(char* str)来分别实现字符串的逆序打印和反向排列
一、逆序打印和反向排列的区别
- 逆序打印:逆序打印的实质是将数组内部的所有元素进行反向输出,而数组本身内部元素下标并未发生改变(具体效果可见后续实现方法)
- 反向排列:反向排列的实质是将原来的数组内部的所有元素下标重新排列为逆序,数组下标会发生改变(具体效果可见后续实现方法)
二、两种功能的实现方法
1.逆序打印(两种)
循环
思路:从最后一个元素一直遍历到第一个元素
代码如下:
#include <stdio.h>
#include <string.h>
void Reverse(char* str) {
//字符串长度
int len = strlen(str);
for (int i = len - 1; i >= 0; i--)
{
//从后到前遍历
printf("%c", str[i]);
}
}
int main()
{
char arr[50];
scanf("%s", &arr);
Reverse(arr);
return 0;
}
运行结果:
递归
思路:从数组的首地址开始判断,若当前地址不等于'\0'时,地址加1,并调用自身函数,直到元素地址为'\0'时达到递归结束条件,依次执行输出语句,至此形成逆序序列
代码如下:
#include<stdio.h>
//递归实现逆序
void Reverse(char* str) {
if (*str) {
Reverse(str + 1);
printf("%c ", *str);
}
}
//此处为模拟实现strlen()函数
//也可直接调用strlen(str),记得引用库函数--#include<string.h>
int my_strlen(char* str) {
int count = 0;
while (*str != '\0') {
count++;
str++;//数组名是数组首元素地址,向右移动指向下一位下标
}
return count;
}
int main() {
char arr[20];
printf("请输入要反向输出的字符串序列:\n");
scanf("%s", arr);
int len = my_strlen(arr);
printf("以下为反向输出的序列打印:\n");
Reverse(arr);
printf("\n以下为 arr数组内元素打印:\n");
for (int i = 0; i < len; i++) {
printf("%c ", arr[i]);
}
return 0;
}
运行结果:
从上述代码及运行结果可以看出arr数组内部元素下标并未发生改变
2.反向排列(两种)
循环
思路:如图,
字符串存入数组,反向排列即将数组内两边的元素及其下标成对交换。
实现过程:交换两边对应的元素(左侧元素下标:left;右侧元素下标:right),左侧元素的下标left加1向右移动,右侧元素的下标right减1向左移动,就这样left不断加1,right不断减1,直到中间只剩下1个元素或0个元素,即left>right,不用再次交换,循环结束
代码如下:
#include<stdio.h>
//方法二:反向排列(循环)
//模拟实现strlen()函数
int my_strlen(char* str) {
int count = 0;
while (*str != '\0') {
count++;
str++;///数组名是数组首元素地址,向右移动指向下一位下标
}
return count;
}
//递归函数
void Reverse(char* str) {
int left = 0;
int right = my_strlen(str) - 1;
//元素及下标交换
while (left < right) {
char temp = str[left];
str[left] = str[right];
str[right] = temp;
left++;
right--;
}
}
int main() {
char arr[20];
int i = 0;
scanf("%s",arr);
int len = my_strlen(arr);
printf("反向排列前数组内元素:");
for (i = 0; i < len; i++) {
printf("%c ", arr[i]);
}
Reverse(arr);
printf("\n反向排列后的序列:%s",arr);
printf("\n反向排列后数组内元素:");
for (i = 0; i < len; i++) {
printf("%c ", arr[i]);
}
return 0;
}
运行结果:
从上述代码及运行结果可以看出arr数组内部元素下标已经发生改变
递归
思路:如下图所示,递归的每一次函数调用都是先两端的元素换序,再中间字符串换序
(这里最好看图比较容易懂)一趟逆序有如下5个步骤,而递归的结束条件是中间绿色方框中的字符剩余个数为0或1个时,递归跳出,排列结束
代码如下:
#include<stdio.h>
//递归函数
void Reverse(char* str) {
int len = strlen(str);
char temp = *str;//步骤(1)
*str = *(str + len - 1);//步骤(2)尾端元素赋给首段元素
*(str + len - 1) = '\0';//步骤(3)方面判断中间字符个数
//递归跳出条件
if (strlen(str + 1) >= 2) {//中间字符剩0个或1个不用逆序
Reverse(str+1);//步骤(4)
}
*(str + len - 1) = temp;//步骤(5)
}
int main() {
char arr[20];
int i = 0;
scanf("%s",arr);
int len = strlen(arr);
printf("反向排列前数组内元素:");
for (i = 0; i < len; i++) {
printf("%c ", arr[i]);
}
Reverse(arr);
printf("\n反向排列后的序列:%s",arr);
printf("\n反向排列后数组内元素:");
for (i = 0; i < len; i++) {
printf("%c ", arr[i]);
}
return 0;
}
运行结果:
同样,数组元素下标发生改变
补充方法
额外的一种递归实现方法:按字符读取打印
#include<stdio.h>
void reverse(){
char input;
input = getchar();//一次读一个字符
if (input != '.')
reverse();
else
return;
printf("%c", input);
}
int main(){
printf("请输入字符串,以回车结束 :\n");
reverse();
printf("\n以上为逆序打印输出!");
return 0;
}
总结
以上就是作者对字符串的逆序输出和反向排列的区别及利用循环和递归方法实现的总结,文中代码部分实现思路来源于B站视频比特鹏哥的C语言课程(鹏哥真的是一位很棒的老师!)。