web-dev-qa-db-ja.com

文字列内の\をエスケープの代わりにリテラルとして使用する

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」として読み込まれます。

6
monkeyMoo
_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;
}
_

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

編集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. 
    }
}
_


EDIT 5:stringMatch()の_const char *_を 'string`に変更すると、それほど複雑ではありません。

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

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

_string a = R"raw(a\sb)raw";
_

文字列内のrawは、任意の区切り文字に置き換えることができることに注意してください。これは、実際の文字列で_)raw_のような部分文字列を使用する場合に使用します。これらの生の文字列リテラルを使用することは、_std::regex_との組み合わせのように、文字をたくさんエスケープする必要がある場合に主に意味があります。

P.S。これですべての答えが得られたので、どれを実装するかによって最良の結果が得られます。

13
Derpy Derp

Xcodeは、「a\sb」の_\s_をエスケープシーケンスとして解釈しているため、その警告を吐き出しますが、_\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」を試したときに観察した問題を正確に投稿してください。


バックスラッシュはこの方法でエスケープする必要があるため、RegexはC++では苦痛になる可能性があります。 C++ 11には、いかなる種類のエスケープも許可しない生の文字列があるため、バックスラッシュをエスケープする必要はありません:R"(a\sb)"

7
bames53