1. ホーム
  2. c++

[解決済み] printf with std::string?

2022-03-02 23:31:59

質問

私の理解では stringstd という名前空間がありますが、なぜ次のようなことが起こるのでしょうか?

#include <iostream>

int main()
{
    using namespace std;

    string myString = "Press ENTER to quit program!";
    cout << "Come up and C++ me some time." << endl;
    printf("Follow this command: %s", myString);
    cin.get();

    return 0;
}

<イグ

プログラム実行の都度 myString は、上の出力のように、一見ランダムに見える3文字の文字列を表示します。

解決方法は?

コンパイル中の原因 printf は型安全ではありません。C言語の意味での変数引数を使用しているからです。 1 . printf にはオプションがありません。 std::string C スタイルの文字列のみです。期待されるものの代わりに何か他のものを使っても、間違いなく望む結果は得られないでしょう。実際には未定義の動作なので、どんなことでも起こりうるのです。

C++を使用しているので、これを解決する最も簡単な方法は、普通に印刷することです。 std::cout というのは std::string は演算子のオーバーローディングによってそれをサポートしています。

std::cout << "Follow this command: " << myString;

何らかの理由でC言語風の文字列を抽出する必要がある場合は c_str() のメソッドを使用します。 std::string を取得することができます。 const char * はヌル文字で終端しています。あなたの例で言うと

#include <iostream>
#include <string>
#include <stdio.h>

int main()
{
    using namespace std;

    string myString = "Press ENTER to quit program!";
    cout << "Come up and C++ me some time." << endl;
    printf("Follow this command: %s", myString.c_str()); //note the use of c_str
    cin.get();

    return 0;
}

のような関数が欲しい場合 printf しかし、型安全性については、可変個体テンプレート(C++11、MSVC12の時点ですべての主要なコンパイラでサポートされています)を見てください。その1つの例として ここで . 標準ライブラリにはそのような実装はありませんが、Boostにはあるかもしれません、具体的には boost::format .


[1]: これは、引数をいくつでも渡すことができるが、関数はそれらの引数の数と型を教えてくれることを頼りにしている、ということです。の場合は printf のような型情報をエンコードした文字列を意味します。 %d 意味 int . 型や数を偽っても、関数はそれを知る標準的な方法を持ちません。ただし、コンパイラによっては、嘘をついたときにチェックして警告を出す機能を備えているものもあります。