2

C++ を使用して、クラスに toString() 関数を実装しようとしています。

void ClassName::toString(string& returnString)
{
    sprintf(returnString.c_str(), "Position: (%f, %f, %f)\n", position.x, position.y, position.y);
}

ただし、このエラーが発生し続けます: const char* 型の引数は char* 型のパラメーターと互換性がありません

これを修正して引数を const にしないにはどうすればよいですか?

4

5 に答える 5

5

これを修正するにはどうすればよいですか?

別のアプローチを使用して、stringstream代わりにまたは補助バッファーを使用してください。

void ClassName::toString(string& returnString)
{
    std::stringstream ss;
    ss << "Position: (" << position.x << ", " << position.y << ", " 
       << position.z << ")\n");
    returnString = ss.str();
}

引数を const ではなくしますか?

しないでください。c_str非 const 型に変更すると、地獄が壊れます。仲間のプログラマーは泣くでしょう。天使は翼を失います。子猫は死にます。原油価格が上昇します。株式市場の暴落。ゾンビ黙示録。

これconstには理由があります。変更しないでください。これを行うと、未定義の動作が発生します。

于 2012-08-09T22:17:59.443 に答える
0

sprintf 用のバッファを作成します。次に、returnString に割り当てます。

void ClassName::toString(string& returnString)
{ 
    char buffer[64] = {}; // expect the length of `Position Info` will not exceed 63
    sprintf(buffer, "Position: (%f, %f, %f)\n", position.x, position.y, position.y);
    returnString = buffer;
}
于 2014-10-29T09:15:30.703 に答える
0

現代の C++ では、次のように言えます。

std::string ClassName::toString() const
{
    return "Position: (" + std::to_string(position.x) + ", "
          + std::to_string(position.y) + ", "
          + std::to_string(position.z) + ")\n";
}

を使用する必要がprintfある場合でも文字列を使用できますが、最初にサイズを変更する必要があります。

std::string ClassName::toString() const
{
    static const int initial_size = 1024;

    std::string s(initial_size);
    int ret = std::snprintf(&s[0], s.size(), "Position: (%f, %f, %f)\n", position.x, position.y, position.y);
    s.resize(ret);

    // handle overflow: print again
    if (s.size() > initial_size)
    {
        std::snprintf(&s[0], s.size(), "Position: (%f, %f, %f)\n", position.x, position.y, position.y);
    }
    return s;
}

&s[0]変更可能な char へのポインター、そして実際には size の配列全体の最初の要素へのポインターを提供することに注意してくださいs.size()

于 2012-08-09T22:31:37.580 に答える
0

c_str()const char *関数によって返されるポインターを使用して文字列の値を変更することは一般的には良い考えではないため、 a を返しc_str()ます。

ところで、あなたがやろうとしていることは無意味です。returnString.append()メソッドを使用するだけです。

ただし、sprintf を使用して行う必要がある場合は、文字列に sprintf の出力を保持するスペースがあることを確認する必要があります。

最初の方法:メソッドで実行できますが、メソッドで文字列バッファーを直接変更した場合に.reserve()返される文字列の内部サイズ カウンターは変更されません(適切なサイズ調整が行われます)。私の知る限り、この方法を使用する必要がなければ問題はありません。.size()sprintf()append().size()

2 番目の方法 (より適切): sprintf の正確な出力長がわかっている場合は、この方法が適しています。.resize()の代わりにメソッドを呼び出す必要があり.reserve()ます。.resize()文字列のサイズ カウンターを適切に調整します。

最後に、次を使用する必要があります。sprintf(const_cast<char *>(returnString.data()), ...

ところで、この全体は良い考えではありません。

PS は、 C スタイルの文字列にするためにヌル ターミネータを追加しないこと.data()を除いて、 と同じです。.**c**_str()

于 2012-08-09T22:34:08.140 に答える
-1

http://www.cplusplus.com/reference/string/string/c_str/

返された配列は、この一連の文字に必要な記憶領域とその終端のヌル文字を含む内部の場所を指しますが、この配列の値はプログラムで変更してはならず、次の呼び出しまで変更されないことが保証されているだけです。文字列オブジェクトの非定数メンバー関数。

返された char * の内容を変更することはできません

次のようなものを試してください:

void ClassName::toString(string& returnString)
{
    char tmp[256];
    sprintf(tmp, "Position: (%f, %f, %f)\n", position.x, position.y, position.y);
    returnString=tmp;
}
于 2012-08-09T22:28:20.087 に答える