raw 文字列を使ってエスケープ文字を省略する - C++ プログラミング

PROGRAM


raw 文字列を使ってエスケープ文字を省略する

C++11 では raw 文字列という、文字列中でエスケープ記号を使わずに文字列リテラルを記載する方法が規定されました。

Xcode 4.6 では使用できますが、Visual Studio 2012 では使用できないので気を付けてください。

 

この raw 文字列を使うには、これまでの文字列定数の引用符よりも手前に R を書いて、文字列定数の最初と最後を丸かっこで括ります。

R"(文字列)"

または、引用符内の丸かっこの外側に同じ文字列を記載することもできます。

R"delimiter(文字列)delimiter"

このとき delimiter という文字列でなければいけないことはなく、同じ文字列であれば大丈夫です。

 

raw 文字列の書式はこのような感じになります。

書式だけだとピンと来ないので、実際のケースに応じた例を見ていきます。

 

エスケープ記号を省略する

たとえばファイルのパスを指定するような場合で、通常の文字列定数と raw 文字列とを比べてみます。

// 通常の文字列では "\" 記号をエスケープする必要があります。

const char* string1 = "C:\\Windows\\System32\\Drivers\\etc";

 

// raw 文字列は R"( で始めて )" で閉じます。その間の記号はエスケープ不要です。

const char* string2 = R"(C:\Windows\System32\Drivers\etc)";

このように raw 文字列では、文字列リテラルの最初と最後が少し混雑しますけど、その内側でエスケープ文字が必要な場合にとても読みやすくなります。

そして、これらはどちらも同じ文字列を表しているので、strcmp 関数で比較すると一致します。

 

実際に書いた改行も文字列になる

raw 文字列は、単にその中でエスケープ不要になるだけでなく、書いた文字がそのまま文字として扱われる性質があります。

そのため、文字列定義の途中でも改行して、そこが実際に改行されている文字列を作ることができます。

// 通常の文字列では "\n" を使って改行していました。

const char* string1 = "First Line\nSecond Line";

 

// raw 文字列なら、実際の改行文字を使って改行できます。

const char* string2 = R"(First Line

Second Line)";

raw 文字列をこのように記載しても、ちゃんとした文字列が生成されます。

もちろん、string1 と string2 とを strcmp 関数で比較すれば一致します。

 

ただし、Xcode 4.6 のような自動インデントに対応しているエディタを使っている場合は注意が必要です。

たとえば raw 文字列に改行文字を入れようと思って実際に改行をしたときに、エディタがインデントのためのタブを挿入してしまうと、そのタブを残したままだとそれも文字列の一部としてしまいます。

// 通常の文字列では "\n" を使って改行していました。

const char* string1 = "First Line\nSecond Line";

 

// raw 文字列なら、実際の改行文字を使って改行できます。(注:インデントも文字として扱われます)

const char* string2 = R"(First Line

    Second Line)";

そのため、このようにタブがうっかり入ったりすると、この例では string1 と string2 とが strcmp 関数で一致しなくなります。

 

引用符を文字列中に含める

引用符を文字列中に含める場合も、raw 文字列であればエスケープ不要です。

// 通常の文字列では、引用符は "\"" を使って改行していました。

const char* string1 = "This is the \"raw\" string.";

 

// raw 文字列なら引用符もそのまま記載できます。

const char* string2 = R"(This is the "raw" string.)";

これができるのは、raw 文字列の終端を示す記号が )" になっているためです。

 

もしもその )" という文字が途中で出てきてしまうような場合には、丸括弧の外側に付けられる delimiter を使用します。

delimiter は好きな文字列を自由につけられるので、表示したい文字とかぶらないようにします。

 

たとえば ** を delimiter として使うことで、文字中に )" を次のようにして含められます。

const char* string = R"**(You can use the words )" using delimiter.)**";

また、hash_code 関数を使えば型毎に一意の値を size_t 型の数値も得られます。

size_t typeHash = info.hash_code();

コンパイラが raw 文字列に対応していれば、間違って文字リテラル中に )" のような終了文字が混ざったときにはコンパイルエラーになるので、そうした時にデリミタを付けてあげるようにします。


[ もどる ]