您的位置:首页 > 大数据 > 人工智能

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

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

一:

首先来非递归的,这个就比较简单了,直接利用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函数的递归调用。

正确输出为:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息