大家好!下面是一个程序,它询问用户一个句子并输出其中的回文数量。
#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;
}
它运作得很好。但是,例如,当我输入“快速棕色堵嘴有蓝眼睛”时,程序显示的回文数量仅为1,但实际上,句子有2个回文:堵嘴和眼睛。问题是“眼睛”这个词有一个句号。那么,当用户输入“我爱中午,晚上和午夜”时,程序如何忽略句点和其他标点符号,例如逗号。中午是一个回文,但由于逗号,该程序无法识别它。
另一个问题是资本化。当用户输入“Madam,我的工作完成”时,我希望这个程序能够工作(并忽略ASCII等价物)。我知道它与 tolower 有关。
总结一下,我希望这个程序有一个功能,其中a)忽略标点符号,b)大写。
哦,“stringstream processtens(句子); ......”的替代方案是什么?相反,我需要这个程序使用 substring(substr)并找到。
请指导我,伙计们!谢谢你,任何一种帮助非常感谢。再次感谢,祝你有愉快的一天!
答案 0 :(得分:2)
答案 1 :(得分: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
来自字符串的末尾。< / p>
代码的核心是检查palindromy(不区分大小写,通过比较下行字符),以及即使失败时立即return false
;否则这两个迭代器会被提前一个。
最后,循环的开头会从字符串中获取非字母字符,因此忽略了这些字符。我们再次检查是否在吞噬之后到达了字符串的末尾;你必须确保只将解析器解除引用到有效元素!
当向前移动的迭代器经过向后移动的迭代器时,循环停止。这是条件distance(it, rt.base()) > 0
的内容:反向迭代器的“基础”实际上是反向迭代器元素之后元素的普通迭代器。因此it
只要从rt
到it
的基数的距离严格大于零,就不会越过rt
。 (当it
和rt
引用相同的元素时,距离恰好是1。)
答案 2 :(得分:0)
我认为有一个检查标点符号的功能。您可能想尝试ispunct