字符串逆序输出与main函数的递归调用

昨天有人问问了我这样一道题,如何不利用第三方变量,将字符串逆序输出。我给出了几种方案,有非递归的,也有递归的。

一:

首先来非递归的,这个就比较简单了,直接利用strlen函数求得字符串长度,然后逆序输出即可。

代码如下:

#include <iostream>
#include <string.h>

void reverse_str(const char *str)
{
	auto len = strlen(str);
	for(int i=len-1; i>=0; --i){
		std::cout << str[i];
	}
}

int main(int argc, char ** argv)
{
	if(argc != 2){
		fprintf(stdout, "Usage %s <string>\n", argv[0]);
		exit(EXIT_FAILURE);
	}

	reverse_str(argv[1]);

	return 0;
}

二:

其次为递归方法,递归的思路是函数压栈,当检测到\0,递归终止,然后函数出栈,逆序打印每个字符。

其中有两点值得注意:

1、字符串作为全局变量

<pre name="code" class="cpp">#include <iostream>

const char *str = "iloveyou";

void reverse_string(const char *)
{
	if(*str != '\0')
		reverse_string(++str);
	
	if(*str != '\0')
		std::cout << *str;

	--str;
}

int main(int argc, char** argv)
{
	reverse_string(str);

	return 0;
}

 

这种递归方法显然可以成功,然后我又想用字符串定义在主函数,利用主函数调用的方式。

2.字符串作为主函数局部变量

(1)++str

我首先用了这样的写法:

//wrong
#include <iostream>
void reverse_string(const char *str)   //error,因为++str如果在底层函数中改变,想要在上一层保留变动结果,需要传递引用。
{
	if(*str != '\0')
		reverse_string(++str);   //
	
	if(*str != '\0')
		std::cout << *str;

	--str;
}

int main(int argc, char** argv)
{
	const char *str = "iloveyou";
	reverse_string(str);

	return 0;
}

这个写法困扰了我好长时间,它总是打印不到第一个字母,后来我突然意识到,如果需要在递归子程序里面改变参数的值,就需要传递引用给它,这样才能保留你要做的改动,并返回给上一层。下面这种写法才是正确的:

#include <iostream>

void reverse_string(const char *&str)   //right,传递引用
{
	if(*str != '\0')
		reverse_string(++str);   
	
	if(*str != '\0')
		std::cout << *str;

	--str;
}

int main(int argc, char** argv)
{
	const char *str = "iloveyou";
	reverse_string(str);

	return 0;
}
(2)str+1

另外一种写法就是直接用str+1,这样你的str指针始终指向不变,只是传递给下一层的参数,是你的str+偏移量的那个地址,相当于tmp = str +偏移量,tmp传给下一层子函数。而不是str++, str++其实是 str = str + 1,str自身指向也改变了。
由于每一层子函数都有自己的str+偏移量结果,自然不需要传递引用了,因为我们不需要也不会改变str的指向,也就不需要--str了。代码如下:

#include <iostream>

void reverse_string(const char *str)   //由于不用改变str,所以不需要传递引用
{
	if(*str != '\0')
		reverse_string(str+1);   //对应str+1
	
	if(*str != '\0')
		std::cout << *str;

	//--str;     //每一层都有自己的str+偏移量
}

int main(int argc, char** argv)
{
	const char *str = "iloveyou";
	reverse_string(str);

	return 0;
}

三:

终极方法:main函数的递归调用实现字符串逆序输出。

1.首先我给出了这样的写法:

#include <iostream>

char* str = "iloveyou";

int main(char *, char **argv = NULL)
{
	if(*str != '\0')
		main(++str);
	if(*str != '\0')
		std::cout << *str;
	--str;

	return 0;
}
这种写法编译有警告,但可执行且输出结果正确。


不过本着好学的精神,我自己把它的几个警告一一解决掉了。

2.完美无敌版如下:

#include <iostream>

const char *str = "iloveyou";

int main(int argc , char** argv = NULL)
{
	char ch = (char)argc;
	if(ch != '\0')
		main(*((int *)const_cast<char*>(++str)));  //const_cast解除const限定
	
	if(ch != '\0')
		std::cout << *str;
	--str;

	return 0;
}
首先给字符串加上const解决第一个警告,但是由于加了const之后,再将str作为参数传递时,接受参数也必须为const,但是main函数参数如上图第二个警告所说,第一个必须为int型,所以先用const_cast去掉str的const限定,将str转为为Int类型,用argc参数接收,然后在函数内部进行强转赋给ch,通过char类型的ch作为判断条件,利用类似子函数递归逆序的方法,实现main函数的递归调用。
正确输出为:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值