【问题标题】:writing a c++ program that takes a string and returns number of palindromes and longest palindrome编写一个接受字符串并返回回文数和最长回文数的 C++ 程序
【发布时间】:2021-11-05 14:47:33
【问题描述】:

我必须编写一个程序,将字符串作为输入并输出字符串中的单词数、回文数和最长回文数。我有一个不错的开始,遍历字符串并返回有多少单词,我知道如何遍历这些单词以找到回文,但我现在非常卡住。这就是我现在所拥有的。任何帮助将不胜感激。

#include <iostream>
#include <string>
int main()
{
    std::string word = "";
    std::string words;
    std::getline(std::cin, words);
    int word_count = 1;
    int palindrome_count = 0;
    for (auto check : words) {
        if (check == ' ') {
            for (int i = 0; i < word.length(); i++) {
                if (word[i] == word[word.length() - 1 - i]) {
                    palindrome_count++;
                }
            }
            word = "";
            word_count++;
        }
        else {
            word = word + check;
        }
    }
    std::cout << word_count << " words" << std::endl;
    std::cout << palindrome_count << " palindromes" << std::endl;
}

【问题讨论】:

  • 是否需要检查字符串中的每个单词是否为回文?
  • 建议:创建一个名为 is_palidrome 的函数,它接受一个字符串并返回一个布尔值,如果字符串是回文则返回 true,否则返回 false。这使您可以更好地拆分逻辑。具有较少职责的较小功能几乎总是更容易工作和验证。现在你要做的就是将字符串分解成单词(std::istringstream 擅长于此)并将每个单词传递给is_palindrome。如果是,数一数,看看它是否比你迄今为止见过的最大回文更大。
  • 是的,我确实需要检查字符串中的每个单词是否是回文

标签: c++ string split counting palindrome


【解决方案1】:

我会将您读过的string 放入words 并将其放入std::istringstream。这简化了逐字提取。

#include <sstream>

int main() {
    // ...

    std::istringstream is(words);
    std::string word;

    while(is >> word) {
        // ...
    }

您现在可以在 word 中一次获得一个词。

检查它是否是回文可以通过从两端搜索word并比较字母直到算法在中间相遇来完成。如果任何一个字母在到中间的途中不匹配,则不是回文。

bool is_palindrome(const std::string& word) {
    auto b = word.begin();
    auto e = word.end();  // points to one char after the last letter
    for(;b < e; ++b) {
        if(*b != *--e) return false;
    }
    return true;
}

或者使用标准算法,std::equal

#include <algorithm>
bool is_palindrome(const std::string& s) {
    return std::equal(s.begin(), s.begin() + s.size()/2, s.rbegin());
}

【讨论】:

    【解决方案2】:

    我们,初学者,应该互相帮助。:)

    你来了。

    #include <iostream>
    #include <sstream>
    #include <string>
    #include <iterator>
    #include <algorithm>
    
    int main() 
    {
        std::string s;
        
        std::cout << "Enter a text: ";
    
        std::getline( std::cin, s );
        
        size_t total_words = 0;
        size_t palindrome_words = 0;
        std::string max_palindrome;
        
        std::istringstream is( s );
        std::string word;
        
        while ( is >> word )
        {
            ++total_words;
            if ( std::equal( std::begin( word ), std::end( word ), 
                             std::rbegin( word ), std::rend( word ) ) )
            {
                ++palindrome_words;
                
                if ( max_palindrome.size() < word.size() )
                {
                    max_palindrome = word;
                }
            }                        
        }
        
        std::cout << "There are " << total_words << " in the entered text.\n";
        std::cout << "Among them there are " << palindrome_words << " palindromes.\n";
        
        if ( palindrome_words != 0 )
        {
            std::cout << "The maximum palindrome is " << max_palindrome << '\n';
        }
        
        return 0;
    }
    

    程序输出可能看起来像

    Enter a text: 12 123 1232 12321 121 21
    There are 6 in the entered text.
    Among them there are 2 palindromes.
    The maximum palindrome is 12321
    

    回文检查可以按照 @Ted Lyngmo 的答案中显示的方式更有效。也就是上面程序中的if语句可以这样写

    if ( std::equal( std::begin( word ), 
                     std::next( std::begin( word ), word.size() / 2 ), 
                     std::rbegin( word ) ) )
    

    至于您的方法,那是不正确的。例如,单词之间可以有多个空格。所以这个 if 语句

      if (check == ' ') {
        for (int i = 0; i < word.length(); i++) {
          if (word[i] == word[word.length() - 1 - i]) {
            palindrome_count++;
          }
        }
        word = "";
        word_count ++;
      }
    

    会产生错误的结果。还有这个if语句

          if (word[i] == word[word.length() - 1 - i]) {
            palindrome_count++;
          }
    

    在 for 循环中,变量 palindrome_count 增加了每两个相等的字母,尽管整个单词不是回文。

    【讨论】:

    • 您好,感谢您的帮助!这段代码运行良好,但唯一的问题是它只处理一行输入。我需要能够接受多于一行的输入,而我能想到的唯一方法是将 get line 作为循环条件调用,但我不知道如何让它工作。有什么想法吗?
    • @gobygonagle 再使用一个循环。例如 while ( std::getline( std::cin, s ) && s[0] != '\n' ) { /* ... */ }
    【解决方案3】:

    不确定什么应该算作分隔符(我猜你也想忽略标点符号)但这是我的尝试:

    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <string_view>
    
    bool isPalindrome(std::string_view word)
    {
        size_t idxLeft{0}, idxRight{word.size()-1};
        while (idxLeft < idxRight) {
            if(word[idxLeft] != word[idxRight]) return false;
            idxLeft++, idxRight--;
        }
        return true;
    }
    
    std::vector<std::string> split(std::string_view text)
    {
        std::vector<std::string> words;
        std::string_view::const_iterator itPrev = begin(text);
        while (itPrev != end(text)) {
            auto itBegin = std::find_if(itPrev, end(text), [](char c){ return std::isalnum(c); });
            auto itEnd = std::find_if(itBegin, end(text), [](char c){ return !std::isalnum(c); });
            if (itBegin == itEnd) break;
            words.emplace_back(itBegin, itEnd);
            itPrev = itEnd;
        }
        return words;
    }
    
    int main()
    {
        std::string text = "redivider, one, two, deified, civic, three, radar, level, four, five, rotor, kayak, six, reviver, seven, eight, racecar, madam, nine, refer, ten, 12345678987654321 $!?no comma";
        std::vector words = split(text);
        auto middle = stable_partition(begin(words), end(words), isPalindrome);
        sort(begin(words), middle, [](auto& word1, auto& word2){return word1.size() < word2.size();});
        std::cout << "----[ Palindromes ]----\n";
        for (auto& word: words) {
            std::cout << word << '\n';
            if (decltype(middle)(&word) == middle-1) std::cout << "----[ Non palindromes ]----\n";
        }
        return 0;
    }
    

    在这里演示:https://godbolt.org/z/7c69WP5Ph

    【讨论】:

    • 我不认为它会在这个程序中发生,但如果word.size() == 0idxRight{word.size()-1}; 将不会有好的结局
    • 奇怪的是,我在发布之前测试了isPalindrome(""),它没有崩溃或花费更长的时间......但我同意与word.empty() 进行预检查会更安全。它还提出了一个问题,“空字符串是回文吗?”嗯……
    猜你喜欢
    • 1970-01-01
    • 2022-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-27
    • 2017-08-23
    • 1970-01-01
    • 2015-02-10
    相关资源
    最近更新 更多