2012-01-04 5 views
0

#stringのstring.compare関数を使用して、2つの文字列str1とstr2を比較しています。クラスに'-'' 'と同等であると考えるように強制する方法はありますか? char_traitsのメンバー関数を見ると、私は.assignがこれを達成できると思っていましたが、私が言っているかのように、str1='-';またはstr1=' ';のように動作しています。私は自分の文字列処理クラスを書き直したくないです。' - 'は文字列クラスの比較に ''を割り当てる方法は可能ですか?

+0

文字の値を比較して比較を行うと思います。つまり、 '45 == 32'と思うようにする必要があります。文字列のコピーを作成し、 '' - ''のすべての出現を ''''で置き換えて比較することはできませんか? – Chad

+0

@Chad:スペースなので、 '32'です。 –

+0

@LightnessRacesinOrbit AH!そこにはスペースがあるとは言えませんでした! – Chad

答えて

1

この動作をするかどうかによって、いくつかの可能性あります:あなたは一度動作にしたい場合は

  • はクラス

でエンコード

  • 一度:単に独自の(カスタム)を使用しますアルゴリズム:

    bool isSpace(char i) { return i == '-' or i == ' '; } 
    
    int compare(std::string const& left, std::string const& right) { 
        typedef std::string::const_iterator ConstIterator; 
        typedef std::pair<ConstIterator, ConstIterator> Result; 
    
        size_t const size = std::min(left.size(), right.size()); 
    
        Result const r = std::mismatch(left.begin(), 
               left.begin() + size, 
               right.begin(), 
               [](char a, char b) { 
                return a == b or (isSpace(a) and isSpace(b)); 
               }); 
    
        if (r.first == left.begin() + size) { // equal up til the end, shorter wins 
        return left.size() < right.size() ? -1 : 
          (left.size() == right.size() ? 0 : 1); 
        } 
    
        // not equal until the end 
        return *r.first < *r.second ? -1 : 1; 
    } 
    

    この動作をクラスiでエンコードする必要がある場合あなたはbasic_stringを使用し、カスタム特性クラスを提供する必要があります。

    traitsクラスは、std::string::compareによって使用されるstatic int compare (const char_type* s1, const char_type* s2, size_t n);関数を提供します。例えばので

    :もちろん

    struct MyTraits: char_traits<char> // too lazy to reimplement everything 
    { 
        static int compare(const char_type* s1, const char_type* s2, size_t n); 
        // definition can be trivially derived from the above version 
    }; 
    
    typedef std::basic_string<char, MyTraits> MyString; 
    

    MyStringは、他のstd::stringと完全に互換性がありません。


    可能であれば、文字列を「正規化」して、「 - 」か「 '」を使用するかどうかを決定してください。それはあなたの人生を楽にします。

  • +0

    私は本当に選択肢がありません。データベースの名前エントリに使われていたように ' - 'を処理する必要がありますが、私たちの分析者は実行時にそれらを使用しないので、ソフトウェアを認識する必要がありますそれ、元。 P – John

    +3

    @ジョン:典型的なアーキテクチャを設計する際に、何度も何度も戻ってくる1つのポイントは、データの外部表現を次のように「適応させる」ことです:PC-Eff TPは、PC Eff TPの等価物です。カスタムメモリ内表現。たとえば、DBレイヤーは、レコードが取り込まれるときに単に ' - 'を ''で置き換えることができ、すべての心配がなくなります。この入力の検証/正規化はかなり一般的です:) –

    +0

    'std :: basic_string'は異なるchar/traits/allocatorを持つ' std :: basic_string'から暗黙的に構築できたらいいと思います。それは多くのことを単純化します。 –

    4

    2つの文字列を比較する前に、 " - "のすべての出現箇所をコピーして ""と置き換えるのはどうですか?

    3

    あり、そのような具体的なユースケースのためのライブラリでは何もありませんが、それはそれを自分で行うのは簡単だ:

    1. は、両方の文字列のコピーを作成します。それぞれ、'-'' 'に置き換えてください。次に、これらの文字列の比較を実行します。

    2. 各文字を繰り返し処理し、記述した追加のセマンティクスとの辞書編集による比較を実行する関数を作成します。これは文字列のコピーを必要としないという利点がありますが、より多くのコードになり、エラーを起こしやすくなります。 「 - 」と「」それらを比較する前に

    +0

    私はカスタム 'char_traits'を使用することで可能と信じています。それが何のためのものではありませんか? –

    +0

    @MooingDuck:おそらく、これらの特性を使用する新しい 'std :: basic_string'インスタンスが必要なのでしょうか?コピーの必要性? (まあ、あなたはそれらの形質を使用することができますが、これは確かにPOLSに違反するでしょう)か、特徴は比較の特徴ですか?私は忘れる。 –

    +0

    あなたはそれがコピーを必要とする新しいクラスであることは間違いありません。それらを置き換えることは非常に速く、あるいはあなたが言うようにカスタム比較を使用しています。私はもう少しエラーが発生しやすいと思っています。いずれにせよトレードオフ。 –

    1

    簡単な方法は、すべてを置き換える文字列、つまりシンプルにあります。

    0

    (コミュニティのwiki、貢献して自由に感じる。)

    あなたは、charの新しいタイプに基づいて、文字列の新しい型を定義することができます。以下はコンパイルされ実行されているようですが、欠落しているか間違っていることがあります。目標はハイフンが自動的にスペースに変換される文字列クラスを定義することです。

    #include<iostream> 
    using namespace std; 
    
    struct newchar { 
         char c; 
         bool operator <(const newchar &other) const { 
           return this->c < other.c; 
         } 
         newchar(char c_): c(c_) { 
           fixme(); 
         } 
         newchar(): c('\0') {} 
         newchar & operator = (const newchar &in) { 
           this->c = in.c; 
           fixme(); 
           return *this; 
         } 
         void fixme() { 
           if(c=='-') 
             c = ' '; 
         } 
    }; 
    
    struct newstring : basic_string<newchar> { 
         string toCharString() const { 
           std :: string s; 
           for(const_iterator i = this->begin(); i != this->end(); i++) { 
             char c = i->c; 
             s += c; 
           } 
           return s; 
         } 
    }; 
    ostream& operator<< (ostream & os, const newstring &ns) { 
         os << ns.toCharString(); 
         return os; 
    } 
    
    int main() { 
         newstring s; 
         s.compare(s); 
         s += 'k'; 
         cout << '<' << string() << '>' << endl; 
         cout << '<' << s << '>' << endl; 
    } 
    
    1

    標準のC++ライブラリは、このための強力なアルゴリズムを提供します。 std::mismatch()を、 ' - 'と ''が同一であることを考慮してカスタム述部と共に使用したいと思われます。 pが異なる最初の文字(または終了イテレータ)で指すイテレータの組で、これに続いて

    bool pred(char c0, char c1) { 
        return c0 == c1 
          || (c0 == '-' && c1 == ' ') 
          || (c0 == ' ' && c1 == '-'); 
    } 
    
    std::string const& s(s0.size() < s1.size()? s0: s1); 
    std::string const& l(s0.size() < s1.size()? s1: s0); 
    auto p = std::mismatch(s.begin(), s.end(), l.begin(), pred); 
    

    :これは次のようになります。その結果を評価する前または後でどの文字列をソートするかを決定する。

    インターフェイスは、より短いシーケンスが最初に必要であるという点で面倒です。両端に制約があるはずです。

    関連する問題