11
bool stringMatch(const char *expr, const char *str) {   
    // do something to compare *(expr+i) == '\\'  
    // In this case it is comparing against a backslash
    // i is some integer
}

int main() {
    string a = "a\sb";
    string b = "a b";
    cout << stringMatch(a.c_str(), b.c_str()) << endl;
    return 1;
}

したがって、現在の問題は次のとおりです。stringMatch関数でデバッグしているときに、Xcodeが「\」を読み取っていない場合、exprはリテラルa\sb'ではなく「asb」としてのみ表示されます。

そして、Xcodeは次の行に警告を吐き出します:string a = "a \ sb":不明なエスケープシーケンス

編集:私はすでに「a \\ sb」を使用しようとしました、それはリテラルとして「a\\sb」として読み込まれます。

4

2 に答える 2

21
bool stringMatch(const char *expr, const char *str) {   
   // do something to compare *(expr+i) == '\\'  
   // In this case it is comparing against a backslash
   // i is some integer
}

int main() {
    string a = "a\\sb";
    string b = "a b";
    cout << stringMatch(a.c_str(), b.c_str()) << endl;
    return 1;
}

C および C++ は、デフォルトでバックスラッシュをエスケープ シーケンスとして扱います。文字列に余分なバックスラッシュを追加して、エスケープ シーケンスとしてバックスラッシュを使用しないように C に指示する必要があります。

これらは、一般的なエスケープ シーケンスです。

  • \a - ベル (ビープ音)
  • \b - バックスペース
  • \f - 用紙送り
  • \n - 改行
  • \r - キャリッジ リターン
  • \t - 水平タブ
  • \\ - バックスラッシュ
  • \' - 一重引用符
  • \" - 二重引用符
  • \ooo - 8 進表現
  • \xdd - 16 進表現

編集: Xcode がマシン上で異常に動作しています。だから私はあなたにこれを提案することができます。

bool stringMatch(const char *expr, const char *str) {   
   // do something to compare *(expr+i) == '\\'  
   // In this case it is comparing against a backslash
   // i is some integer
}

int main() {
    string a = "a" "\x5C" "sb";
    string b = "a b";
    cout << stringMatch(a.c_str(), b.c_str()) << endl;
    return 1;
}

宣言内のスペースについて心配する必要はありません。Xcode は、スペースでstring a区切られた文字列を連結します。

編集 2:実際、Xcode は"a\\b"文字どおりに読み取っています。これが、エスケープされたバックスラッシュを処理する方法です。string a = "a\\sb"コンソールに出力すると、 a\sb. ただし、メソッド間を引数として、またはプライベート メンバーとして渡す場合はstring a、文字どおり余分なバックスラッシュが必要になります。余分なバックスラッシュを無視するように、この事実を考慮してコードを設計する必要があります。糸をどう扱うかはあなた次第です。

編集3: Edit 1ここでの最適な答えですが、別の答えです。

メソッドにコードを追加してstringMatch()、二重のバックスラッシュを単一のバックスラッシュに置き換えます。

関数の最初に次の行を追加するだけです。

expr=[expr stringByReplacingOccurrencesOfString:@"\\\\" withString:@"\\"];

これにより、二重バックスラッシュの問題が解決されます。

編集 4: 一部の人々は、編集 3は ObjectiveC であり、したがって最適ではないと考えているため、ObjectiveC++ の別のオプションです。

void searchAndReplace(std::string& value, std::string const& search,std::string const& replace)
{
    std::string::size_type  next;

    for(next = value.find(search);        // Try and find the first match
        next != std::string::npos;        // next is npos if nothing was found
        next = value.find(search,next)    // search for the next match starting after
                                          // the last match that was found.
       )
    {
        // Inside the loop. So we found a match.
        value.replace(next,search.length(),replace);   // Do the replacement.
        next += replace.length();                      // Move to just after the replace
                                                       // This is the point were we start
                                                       // the next search from. 
    }
}


編集 5:const char * inを 'string` に変更するstringMatch()と、複雑さが軽減されます。

expr.replace(/*size_t*/ pos1, /*size_t*/ n1, /*const string&*/ str );

編集 6: C++11 以降、次のようなものが存在しますraw string literals。これは、エスケープする必要がないことを意味します。代わりに、次のように記述できます。

string a = R"raw(a\sb)raw";

raw文字列内の は、選択した任意の区切り文字に置き換えることができることに注意してください。)rawこれは、実際の文字列のように部分文字列を使用したい場合です。std::regex. _

PS これですべての答えが得られたので、どれを実装して最良の結果が得られるかはあなた次第です。

于 2012-08-24T05:19:21.113 に答える
9

\sXcodeは、「a \ sb」でエスケープシーケンスとして解釈しているため、その警告を吐き出します\sが、有効なエスケープシーケンスではありません。s文字列が「asb」になるように置き換えられます。

のようにバックスラッシュをエスケープするの"a\\sb"が正しい解決策です。これがどういうわけかうまくいかなかった場合は、詳細を投稿してください。

これが例です。

#include <iostream>
#include <string>

int main() {
    std::string a = "a\\sb";
    std::cout << a.size() << ' ' << a << '\n';
}

このプログラムの出力は次のようになります。

4 a \ sb

別の出力が得られた場合は、投稿してください。また、以前に「a\\sb」を試したときに観察した問題を正確に投稿してください。


バックスラッシュをこのようにエスケープする必要があるため、正規表現はC++では苦痛になる可能性があります。C ++ 11には生の文字列があり、どのような種類のエスケープも許可されていないため、バックスラッシュをエスケープする必要はありませんR"(a\sb)"

于 2012-08-24T05:14:06.893 に答える