【问题标题】:Why is my while loop not terminating when i < 0?为什么当 i < 0 时我的 while 循环没有终止?
【发布时间】:2020-07-17 21:15:20
【问题描述】:

抱歉这个菜鸟问题。 我在课堂上有以下作业代码(包括作业描述):

编写一个程序,要求用户输入一个字符串,然后将其传递给一个 void 递归函数,该函数反向显示该字符串。该函数的原型是:

void reverse(string s, int i);

函数调用将是:

reverse(strIn, strIn.length());

典型的运行将是:

输入一个字符串:

四分和七年前..

.. oga sraey neves dna erocs ruoF

// Actual code
#include <iostream>
#include <string>

void reverse(std::string, int);

int main() {
  std::string input;

  std::cout << "Enter a string." << std::endl;

  getline(std::cin, input);

  int i = input.length() - 1;

  reverse(input, i);

  return 0;
}

void reverse(std::string input, int i) {
  while (i >= 0) {
    std::cout << input.at(i);
    i--;
    reverse(input, i);
  }
}

我假设每次减去 1 将显示字符串中的最后一个字符,并将循环条件设置为 i &gt;= 0 将使循环在字符串中没有更多字符时终止。但我得到以下输出:

sleepy@mooncell ~/CMPSC121/Activities $ ./a.out
Enter a string.
help
plehhehhlehhehh

我无法弄清楚我在这里做错了什么。非常感谢您的帮助!

【问题讨论】:

  • 您的循环确实终止了...问题是您的程序逻辑需要if 而不是while
  • 使用递归时不需要循环
  • @EduardoPascualAseff 谢谢,这解决了我的问题!

标签: c++ loops recursion while-loop


【解决方案1】:

这个函数

void reverse(std::string input, int i) {
  while (i >= 0) {
    std::cout << input.at(i);
    i--;
    reverse(input, i);
  }
}

不是纯递归的,因为它使用了一个while循环。

按值传递字符串也是一个坏主意。并且字符串中的位置应该具有 std::string::size_type 类型。

第二个参数可以有一个默认参数。在这种情况下,函数调用看起来会简单得多

reverse( input );

请注意,当将空字符串传递给函数时,这些语句可能会调用未定义的行为

int i = input.length() - 1;

reverse(input, i);

因为在这种情况下,变量 i 将具有最大值。就是这个声明

int i = input.length() - 1;

实际上将等价于

int i = std::string::size_type( -1 );

您需要的是以下内容

void reverse( const std::string &s, std::string::size_type i = 0 ) 
{
    if ( i < s.size() )
    {
        char c = s[i];
        reverse( s, i + 1 );
        std::cout << c;
    }
}

这是一个演示程序。

#include <iostream>
#include <string>

void reverse( const std::string &s, std::string::size_type i = 0 ) 
{
    if ( i < s.size() )
    {
        char c = s[i];
        reverse( s, i + 1 );
        std::cout << c;
    }
}

int main() 
{
    const char *s = "Hello bbchan";

    std::cout << s << '\n';

    reverse( s );

    std::cout << '\n';

    return 0;
}

它的输出是

Hello bbchan
nahcbb olleH

更好的方法是用下面的方式定义函数,如下面的演示程序所示。在这种情况下,您可以例如在文件中以相反的顺序写入字符串。

#include <iostream>
#include <string>

std::ostream & reverse( const std::string &s, 
                        std::string::size_type i = 0, 
                        std::ostream &os = std::cout ) 
{
    if ( i < s.size() )
    {
        char c = s[i];
        reverse( s, i + 1, os );
        os << c;
    }

    return os;
}

int main() 
{
    const char *s = "Hello bbchan";

    std::cout << s << '\n';

    reverse( s ) << '\n';

    return 0;
}

【讨论】:

  • 它是递归的……因为它会调用自己。只是逻辑不好。
  • 只需将 OP 函数中的 while 更改为 if 即可,而且要简单得多。
  • @AdrianMole 这并不简单。它需要指定字符串的长度。
  • 谢谢,感谢清理后的代码。我正在尝试学习最佳实践,但我自己很难! (我没有从教授那里得到太多意见——事实上我没有得到任何意见)
  • 在 OP 的作业中,声明如下:“函数调用将是:reverse(strIn, strIn.length());。”
【解决方案2】:

这是因为你试图同时执行递归和while循环,只要去掉while循环就可以了,代码应该是这样的:

// Actual code
#include <iostream>
#include <string>

void reverse(std::string, int);

int main() {
    std::string input;
    std::cout << "Enter a string." << std::endl;
    getline(std::cin, input);
    int i = input.length() - 1;
    reverse(input, i);
    return 0;
}
void reverse(std::string input, int i) {
    if(i <0)
        return;
    std::cout << input.at(i);
    i--;
    reverse(input, i);
}

【讨论】:

  • 是什么原因导致函数继续输出字符?我试图弄清楚它是如何输出这些字符的,但很难想象它。
  • @bbchan 这是因为你正在尝试执行递归并且仍然处于while循环中,我建议你尝试使用笔和纸看看有什么问题这是最好的学习方法