【问题标题】:Counting the Number of Palindromes in a Sentence计算一个句子中的回文数
【发布时间】:2012-01-25 05:43:29
【问题描述】:

大家好!下面是一个程序,它询问用户一个句子并输出其中的回文数。

#include<iostream>
#include<string>
#include<sstream>

using namespace std;

bool isPalindrome (const std::string& s) {
    for (int i = 0; i < (s.length())/2; ++i) {
        if (s[i] != s[s.length()-1 - i])
            return false;
        else
            return true;
    }
}


int main() {
    string sentence;
    int counter=0;
    cout << "Please input a sentence." << endl;
    getline(cin, sentence);
    stringstream processtokens(sentence);
    for(string word; processtokens >> word;) 
        if(isPalindrome(word)) 
            ++counter;
    cout << "Number of Palindromes are : " << counter << endl;
}

它工作得很好。但是例如,当我输入“The quick brown gag has a blue eye.”时,程序显示的回文数只有 1,但实际上,该句子有 2 个回文:gag 和 eye。问题是“眼睛”这个词有句号。那么,当用户输入“我喜欢中午、晚上和午夜”时,程序如何忽略句点和逗号等其他标点符号。 Noon 是回文,但由于逗号,程序无法识别它。

另一个问题是大写。当用户输入“女士,我的工作已经完成”时,我希望这个程序能够工作(并忽略 ASCII 等价物)。我知道这与tolower有关。

总而言之,我希望这个程序有一个函数,它a)忽略标点符号和b)大写。

哦,“stringstream processtokens(sentence);...”的替代方法是什么?相反,我需要这个程序使用 substring (substr) 并找到。

请指导我,伙计们!谢谢您,非常感谢您提供任何帮助。再次感谢,祝您有美好的一天!

【问题讨论】:

  • 您已经描述了几乎所有您需要做的事情。在进行过程中将所有内容都转换为小写,并跳过非字母。你快到了。

标签: c++ function pointers palindrome


【解决方案1】:

您可以使用ispunct 并忽略任何ispunct 返回true 的字符。您还应该在调用 tolower()

中包含您的字符比较

【讨论】:

  • 只是想知道,tolower() 在遇到数字时会抛出异常吗?还是继续前进?
  • @Farhad:遇到数字,返回值不变。
  • @Oleksi:谢谢!但是我如何忽略它们呢?我已经完成了 bool 函数,但我不知道接下来要做什么来“忽略”这些字符。请,谢谢!
  • @CandaceParker- 您可以使用std::remove_if 算法从输入字符串中删除所有标点符号:string.erase(std::remove_if(string.begin(), string.end(), ::to_lower), string.end()).
【解决方案2】:

也许这个小练习可以用来介绍一些不错的 C++ 特性,例如迭代器:

inline bool is_letter(char c)
{ return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); }


bool is_palindrome(const std::string & s)
{
    std::string::const_iterator it = s.begin();
    std::string::const_reverse_iterator rt = s.rbegin();

    while (it != s.end() && rt != s.rend() && std::distance(it, rt.base()) > 0)
    {
        // Skip non-letters
        while (it != s.end() && !is_letter(*it)) { ++it; }
        while (rt != s.rend() && !is_letter(*rt)) { ++rt; }

        if (it == s.end() || rt == s.rend()) { break; }

        // Check palindromy
        if (std::tolower(*it) != std::tolower(*rt)) { return false; }

        // Move on
        ++it;
        ++rt;
    }

    return true;
}

诀窍是从两端攻击字符串。为此,我们有一个普通的迭代器 it,来自字符串的开头,以及一个 reverse 迭代器,rt,来自字符串的结尾。

代码的核心是检查回文(不区分大小写,通过比较小写字符),即使失败也立即return false;否则这两个迭代器会提前一个。

最后,循环的开头会吞噬字符串中的非字母字符,因此会完全忽略这些字符。我们再次检查是否在 gobbling 后到达了字符串的末尾;您必须确保仅将迭代器取消引用到有效元素!

当向前移动的迭代器超过向后移动的迭代器时,循环停止。这是条件distance(it, rt.base()) &gt; 0 的内容:反向迭代器的“基础”实际上是一个普通的迭代器到元素之后 反向迭代器的元素。所以it 没有跨越rt,只要从it 到rt 的底部的距离严格大于零。 (it和rt指向同一个元素时,距离正好为1。)

【讨论】:

  • 非常感谢!你有很大的帮助!但是,当我运行程序并输入“Hello noon,我爱你!”时,它显示 2 作为回文数。我想知道为什么会这样……即便如此。我很感激,因为你清楚地向我解释了这些。非常感谢!
  • 哦,我的立场是正确的。 “我”本身就是一个回文!再次感谢你!祝你有美好的一天!
【解决方案3】:

我认为有一个检查标点符号的功能。你可能想试试ispunct

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-15
    • 1970-01-01
    • 1970-01-01
    • 2015-08-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多