2012-01-25 13 views
1

おはようございます!以下は、ユーザに文章を要求し、文章の数を出力するプログラムです。文章中の回文の数を数える

#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つの回文:ギャグと目があります。問題は、単語 "eye"にピリオドがあることです。だから、たとえば、ユーザーが「正午、夕方、真夜中が好き」と入力したときに、プログラムはカンマのようなピリオドやその他の句読点を無視できます。正午は回文ですが、プログラムはカンマのためにそれを認識しません。

もう1つの問題は大文字です。ユーザーが「マダム、私の仕事は終わった」と入力したときに、このプログラムを動作させて(そしてASCIIの同等物を無視する)私はそれがtolowerと関係があることを知っています。要約する

、私はこのプログラムは、a)のは句読点マークおよびb)総額を無視機能を持っていると思います。

また、「stringstream processtokens(sentence);」の代替手段は何ですか?むしろ、私は部分文字列(substr)を使用し、を見つけるためにこのプログラムが必要です。

私をガイドしてください!ありがとうございました、そしてどんな種類の助けもありがとうございます。おかげさまで、ありがとうございました!

+2

あなたはすでにあなたがする必要があるほとんどすべてを説明しました。あなたはすべてを小文字に変換し、非文字をスキップします。あなたはほとんどそこにいます。 –

答えて

0

句読点をチェックする機能があると思います。試してみるとよいかもしれませんispunct

2

ispunctを使用して、ispunctがtrueを返す文字をすべて無視します。あなたも呼び出しtolower(であなたの文字比較をラップする必要があります)

+0

ちょうど不思議ですが、tolower()は数字に遭遇したときに例外をスローしますか?それともちょっと進んでいますか? – fdh

+0

@Farhad:数値が出現すると、返される値は変更されません。 – omggs

+0

@オレクシ:ありがとう!しかし、どうすればそれらを無視できますか?私はブール関数を実行しましたが、それらの文字を "無視"するために次に何をすべきかわかりません。お願いしてありがとう! 'string.erase(STD :: remove_if(string.begin()、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が文字列の先頭から来ており、の逆イテレータのrtが文字列の最後から来ています。

コードの核心は、パリンドロミー(大文字と小文字を区別しないで大文字小文字を区別しない)のチェックであり、失敗の偶数の場合は即時return falseです。それ以外の場合は、2つのイテレーターが1つ進められます。

最後に、ループの先頭は文字列の文字以外の文字をぎこちなく詰め込むので、これらはフラットアウトされません。私たちは、揺るがした後に弦の終わりに達したかどうか再度確認します。あなたは、イテレータを妥当な要素に逆参照しないように注意しなければなりません!

ループは、前進移動イテレータが後退移動イテレータを過ぎたときに停止します。これは条件distance(it, rt.base()) > 0の内容です:逆イテレータの "基底"は実際にはの要素への通常のイテレータで、の逆イテレータの要素の後です。従って、itからまでの距離がゼロよりも厳密に大きい場合には、itからの距離がrtの距離に厳密に等しい限り、rtを越えていません。(itrtは同じ要素を参照するときの距離が正確に1である。)

+0

ありがとうございました!あなたは大きな助けになっています!しかし、私がプログラムを実行し、 "こんにちは正午、私はあなたを愛して!"と入力すると、回文の数として2が表示されました。なぜそういうのだろうと思っています... でもそうです。あなたが私にそのことを明確に説明したので、とても感謝しています。どうもありがとうございます! –

+0

ああ私は訂正した。 "私"は回文そのものです!ありがとうございました!良い一日を! –

関連する問題