【问题标题】:C++ Palindrome program always giving 0 (false) as an output problem; Where is my code wrong?C++ Palindrome 程序总是给出 0(假)作为输出问题;我的代码哪里错了?
【发布时间】:2019-10-12 12:45:40
【问题描述】:

问题是它总是输出 0(假)作为结果。问题可能出在 isPalindrome 函数中,但我无法确定确切的位置。如果有人提供帮助将不胜感激。

#include <iostream>
#include <cmath>
#include <string>
using namespace std;

bool isPalindrome(string word)
{
    bool result;

    for (int i = 0; i <= word.length() - 1; i++)
    {
        if (word.at(i) == word.length() - 1)
        {
            result = true;
        }
        else
        {
            result = false;
        }
        return result;
    }
}

int main()
{
    string word1;
    int count;
    cout << "How many words do you want to check whether they are palindromes: " << flush;
    cin >> count;

    for (int i = 0; i < count; i++)
    {
        cout << "Please enter a word: " << flush;
        cin >> word1;
        cout << "The word you entered: " << isPalindrome(word1);
    }
}

【问题讨论】:

  • 你对这一行的意图是什么:if (word.at(i) == word.length() - 1)
  • 另外:试着逐行分析这个问题。使用调试器,这样您就可以准确地看到问题出在哪里。
  • 检查位置0的字母是否与最后一个位置的字母相同。然后继续检查位置 1 和位置 - 2 的字母,依此类推。
  • word.length -1 不返回字母。同样,通过返回 true 或 false,您不会继续循环而是退出函数,因此这永远不会起作用。
  • 您建议使用哪一行代码来检查第一个和最后一个字母等等,直到您检查所有这些并确定它是否是回文?跨度>

标签: c++ function palindrome


【解决方案1】:

试试这个:

bool isPalindrome(string word)
{
    bool result = true;
    for (int i = 0; i < word.length() / 2; i++) //it is enough to iterate only the half of the word (since we take both from the front and from the back each time)
    {
        if (word[i] != word[word.length() - 1 - i]) //we compare left-most with right-most character (each time shifting index by 1 towards the center)
        {
            result = false;
            break;
        }  
    }    
    return result;
}

【讨论】:

  • 附带说明:我认为拥有变量 result 并使用它没有任何优势。正如我在回答中所做的那样,直接返回 true 或 false 会更简单。
  • @Andreas 基本上是的,但是 - 也许您不知道某些大型工业领域(例如 MISRA)所遵循的编码风格。我会以更轻松的方式说:只要不是很不方便或对性能不重要,请始终在函数中保留一个 return 语句。这是关于防止错误的证明,例如忽略资源的释放(足以提及解锁互斥锁)或在离开函数之前应该完成的任何“清理”。即使显然没有这样的风险 - 这是关于 this 的安全习惯和 this 的优雅(源自前一个动机)。
  • @Andreas ...此类指南的另一个动机是:更容易维护(当您需要更改返回的格式或编辑“清理”部分时(这实际上与我上面所说的有关 -所以更安全,更方便)和更容易调试(一个出口点)。我推荐你stackoverflow.com/questions/36707/…,其中给出了几个优点和缺点。当然我既不同意也不遵守严格和固执的“总是一个return”。只需从这些中挑选最适合您的。
  • 感谢您的信息。这很有趣。
【解决方案2】:

在此声明中

if (word.at(i) == word.length() - 1)

比较运算符的右侧表达式永远不会改变,其类型为std::string::size_type 而不是char。你的意思是

if (word.at(i) == word.at( word.length() - 1 - i ))

但是使用成员函数 at 没有任何意义。您可以使用下标运算符。例如

if ( word[i] == word[word.length() - 1 - i ] )

并且循环应该有 word.length() / 2 次迭代。

同样在循环中,您将覆盖变量结果。所以你总是返回变量的最后一个值。尽管字符串不是回文,但它可以等于 true。

参数也应该是引用类型。否则,将创建传递参数的冗余副本。

函数可以通过以下方式定义

bool isPalindrome( const std::string &word )
{
    std::string::size_type i = 0; 
    std::string::size_type n = word.length();

    while ( i < n / 2 && word[i] == word[n - i - 1] ) i++;

    return i == n / 2;
}

另一种方法如下

bool isPalindrome( const std::string &word )
{
    return word == std::string( word.rbegin(), word.rend() );
}

虽然这种方法需要创建原始字符串的反向副本。

最简单的方法是使用标准算法std::equal。这是一个演示程序

#include <iostream>
#include <string>
#include <iterator>
#include <algorithm>

bool isPalindrome( const std::string &word )
{
    return std::equal( std::begin( word ), 
                       std::next( std::begin( word ), word.size() / 2 ),
                       std::rbegin( word ) );
}

int main() 
{
    std::cout << isPalindrome( "123454321" ) << '\n';

    return 0;
}

【讨论】:

    【解决方案3】:

    我希望这篇文章也对您有所帮助(也更正了警告):

    bool isPalindrome(string word)
    {
        bool result = false;
    
        int lengthWord = (int)word.length();
    
        for (int i = 0; i <= (lengthWord / 2); ++i)
        {
            if (word.at(i) == word.at(lengthWord - i -1))
            {
                result = true;
                continue;
            }
            result = false;
        }
        return result;
    }
    

    【讨论】:

    • 你应该尽快打破循环,因为它明显是错误的。这个效率低下。此外,您不必在每次相等时都重新分配 true 。在循环之前初始化一次就足够了(请随意查看我的答案)。
    • 真的 :)。感谢您的提示。
    【解决方案4】:

    两个可能的问题。

    你似乎在比较一个字符和一个数字

    if (word.at(i) == word.length() - 1)

    不应该这样吗

    if (word.at(i) == word.at(word.length() - i))?

    if 语句中有 3 个返回,因此无论结果如何,它只会在返回调用函数之前比较一个字符。

    作为一个技巧,在循环内重复调用.length,总是返回相同的值,浪费时间并使代码更难理解。

    一旦发现不匹配,您需要立即返回。如果您正在寻找回文,则只需将单词的前半部分与后半部分以相反的顺序进行比较。类似的东西

    bool isPalindrome(string word)
    {
        for (int i = 0, j= word.length() - 1; i<j; i++, j--)
        // i starts at the beginning of the string, j at the end.
        // Once the i >= j you have reached the middle and are done.
        // They step in opposite directions
        {
            if (word[i] != word[j])
            {
                return false;
            }              
        }
        return true;
    }
    

    【讨论】:

      【解决方案5】:

      函数isPalindrome中的循环只会执行一次,因为return语句在循环的第一次迭代中是无条件执行的。我确定这不是故意的。

      要确定一个字符串是否为回文,循环必须执行多次。只有在计算完最后一个字符之后(在循环的最后一次迭代中),才可以使用 return 语句,除非您事先确定该字符串不是回文。

      另外,在函数isPalindrome中,下面的表达式是无意义的,因为你是在比较字母的ASCII码和字符串的长度:

      word.at(i) == word.length() - 1
      

      因此,我建议该函数使用以下代码:

      bool isPalindrome(string word)
      {
          for (int i = 0; i < word.length() / 2; i++)
          {
              if (word.at(i) != word.at( word.length() - i - 1) ) return false;
          }
      
          return true;
      }
      

      【讨论】:

      • 只迭代单词的一半就足够了:i &lt; word.length() / 2(因为我们从前面和后面都取了 - 朝向中心)。
      • 感谢您指出这一点。我已经相应地编辑了我的答案。
      【解决方案6】:

      正如您问题下的 cmets 中所讨论的那样。你在代码中犯了一些错误。

      你的函数或多或少应该是这样的:

      bool isPalindrome(string word) { 
      
          bool result = true; 
      
          for (int i = 0; i <= word.length() - 1; i++)
          { 
              if (word.at(i) != word.at(word.length() - 1 -i))     
              { 
                  return false; 
              } 
          } 
          return result;
      }
      

      【讨论】:

      • 它无法工作。你总是在与最后一个字符进行比较。
      • 这个答案不正确,因为它永远不会返回 true。
      • @Andreas Wenzel:我很马虎。修好了。
      • @bloody:见上文。
      • 是的,现在好多了:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-13
      • 2014-03-01
      • 1970-01-01
      • 2016-08-02
      • 2016-12-20
      • 1970-01-01
      相关资源
      最近更新 更多