2

たとえば、バックスラッシュ-nをそのままにして(フォーマットなしstd::string my_str( "foobar\n" );で)文字通り書き込みたいと思います。std::ostream&

おそらくmy_str、最初にバックスラッシュをダブルバックスラッシュに変換する書式設定関数で変換する必要がありますか?そのための標準ライブラリ関数はありますか?

それとも、私が渡すことができるディレクティブがありstd::ostream&ますか?

4

4 に答える 4

6

より大きな文字列に対してこれを行う最も簡単な方法は、生の文字列リテラルを使用することです。

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);
}
于 2013-02-13T07:24:42.267 に答える
4

は定数リテラルなので、"foobar\n"と書くだけで、になり、安心してお任せいただけます。"foobar\\n""\\""\"n

あなたが「フォーマット」と呼ぶものはそうではありません。

ストリームは文字列をフォーマットしません。"\n"withの置換はchar(10)、リテラルから実際の値を生成するときにコンパイラーによって行われます。(ostreamは、基盤となるプラットフォームで必要な場合に最大で変換char(10)されますが、それは別の話です)。{ char(10), char(13) }

于 2013-02-13T07:33:23.253 に答える
2

これはまたはとは関係ありませstd::ostreamstd::string。は、すでに行末を意味"foobar\n"するリテラルです。\n

2つのオプションがあります。

  1. エスケープ\n記号\

    std::string str("foobar\\n");

  2. 最新のC++11生文字列リテラルを使用する

    std::string str(R"(foobar\n)");
于 2013-02-13T07:43:28.043 に答える
2

「バックスラッシュ+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

したがって、あなたが書いたものを変換しているのはあなたのストリームではなく、コンパイラです。ユースケースに応じて、次のいずれかを行うことができます。

  • コードに記述されているように文字列を変更します:using "foobar\\n"(これにより長さが1増加することに注意してください)
  • ストリーミング中に変換を実行して、印刷できない文字の16進コードまたはエスケープコードを印刷します

1 Windowsでは、'\n'文字は"\r\n"テキストモードで(キャリッジリターン+ラインフィード)に変換されます。

于 2013-02-13T07:53:04.200 に答える