たとえば、バックスラッシュ-nをそのままにして(フォーマットなしstd::string my_str( "foobar\n" );
で)文字通り書き込みたいと思います。std::ostream&
おそらくmy_str
、最初にバックスラッシュをダブルバックスラッシュに変換する書式設定関数で変換する必要がありますか?そのための標準ライブラリ関数はありますか?
それとも、私が渡すことができるディレクティブがありstd::ostream&
ますか?
たとえば、バックスラッシュ-nをそのままにして(フォーマットなしstd::string my_str( "foobar\n" );
で)文字通り書き込みたいと思います。std::ostream&
おそらくmy_str
、最初にバックスラッシュをダブルバックスラッシュに変換する書式設定関数で変換する必要がありますか?そのための標準ライブラリ関数はありますか?
それとも、私が渡すことができるディレクティブがありstd::ostream&
ますか?
より大きな文字列に対してこれを行う最も簡単な方法は、生の文字列リテラルを使用することです。
std::string my_str(R"(foobar\n)");
括弧が必要な場合は、区切り文字を使用します。
R"delim(foobar\n)delim"
エスケープコードなどを文字列に保持できるものは何も知りませんが、この例std::transform
のように、std::ostream_iterator<std::string>
宛先と必要なケースを処理する関数を使用して出力します。
std::string filter(char c) {
if (c == '\n') return "\\n";
if (c == '\t') return "\\t";
//etc
return {1, c};
}
int main() {
std::string str{"abc\nr\tt"};
std::cout << "Without transform: " << str << '\n';
std::cout << "With transform: ";
std::transform(std::begin(str), std::end(str), std::ostream_iterator<std::string>(std::cout), filter);
}
は定数リテラルなので、"foobar\n"
と書くだけで、になり、安心してお任せいただけます。"foobar\\n"
"\\"
"\"
n
あなたが「フォーマット」と呼ぶものはそうではありません。
ストリームは文字列をフォーマットしません。"\n"
withの置換はchar(10)
、リテラルから実際の値を生成するときにコンパイラーによって行われます。(ostreamは、基盤となるプラットフォームで必要な場合に最大で変換char(10)
されますが、それは別の話です)。{ char(10), char(13) }
これはまたはとは関係ありませstd::ostream
んstd::string
。は、すでに行末を意味"foobar\n"
するリテラルです。\n
2つのオプションがあります。
\n
記号\
std::string str("foobar\\n");
std::string str(R"(foobar\n)");
「バックスラッシュ+n」はストリームによってフォーマットされていません。たとえば、の長さstd::string("\n")
は1です(2ではありません)。同様'\n'
に、単一の文字です。バックスラッシュ+nを書き込むという事実は、印刷不可能な(およびASCII以外の)文字を表すための単なるショートカットです。
別の例として、'\x0a' == '\n'
(0a
改行文字の16進コードであるため)。そしてstd::string("\x0a").size() == 1
また。
(Linux 1の場合)を開いてそのストリームにstd::ofstream
書き込むと、 1バイトを含むファイルになります。その16進値はです。'\x0a'
0a
したがって、あなたが書いたものを変換しているのはあなたのストリームではなく、コンパイラです。ユースケースに応じて、次のいずれかを行うことができます。
"foobar\\n"
(これにより長さが1増加することに注意してください)1 Windowsでは、'\n'
文字は"\r\n"
テキストモードで(キャリッジリターン+ラインフィード)に変換されます。