3

カスタム文字列クラスを表す独自のクラスがあります。私はVS2012RCを使用しています。クラス CustomString のいくつかの演算子をオーバーロードしました。

ここにいくつかのコードがあります:

CustomString::CustomString(string setstr)
{           
    str = setstr;
}

CustomString::operator const char *()
{   
    return (this->str.c_str());
}

CustomString &CustomString::operator = (char *setstr)
{
    str = setstr;
    return *this;
}

オブジェクトを定義して、次のように使用できます。

CustomString str = "Test string";

結果を次のように印刷できます。

printf(str);

printf((string)(str).c_str());

printf((string)(str).data());

printf("%s\n",(string)(str).c_str());

printf("%s\n",(string)(str).data());

そして、エラーはありません。

しかし、私がこのように使用すると:

printf("%s\n", str);

msvcr110d.dll に例外あり(メモリアクセスエラー)

printf(str)は問題ないのに、printf("%s\n",str)は問題ないのはなぜですか?

printf("%s\n",str)を使用するようにコードを変更するにはどうすればよいですか?

...

何時間ものグーグル検索の後、明示的なキャスト (string)、static_cast (str)、および _str() メソッドが null で終わる文字を追加していることがわかりました: '\0';

コードを次のように変更しました。

printf("%s\n",str + '\0');

そしてそれはうまくいきました!

カスタム コンストラクターを変更して null で終わる文字列を追加し、null で終わる文字で正しい値を渡して、次のコードを機能させる方法はありますか。

printf("%s\n",str);
4

4 に答える 4

3

は使用しないprintfでください。C++よりもCに似ています。代わりに、iostreamsを使用してください。これは、独自のカスタムクラスをフォーマットして、ファイルまたはstdoutに送信するための機能を提供します。

これがあなたのために働くかもしれない簡単な(テストされていない)例です:

std::ostream& operator<< (std::ostream &os, const CustomString& str)
{ 
    os << str.data();
    return os; 
} 

そして、次のようなことを行うことで、カスタム文字列をstdoutに出力します。

CustomString str;
// put some text in the custom string, then:
std::cout << str << std::endl;
于 2012-08-22T09:05:48.297 に答える
3

printf は次のように定義されます。

int printf(char const *fmt, ...)

クラスまたは構造体を ... 引数リストに渡すと、未定義の動作が発生し、クラスとコンパイラに応じて、動作またはクラッシュするか、ランダムに何かを実行する可能性があります (3 つすべてを見ました)。

printf(str)

char * が必要で、コンパイラは適切なキャスト演算子があることを検出し、それを呼び出します。str に % が含まれているかどうかわからないため、これは非常に危険であることに注意してください。

だから、あなたはしたいのですprintf("%s", str)が、あなたが言ったように、それはうまくいきません. 一部のコンパイラは警告を表示します (ただし、gcc によって生成される「警告: これはクラッシュします」は、私の意見では、非常によく考えられていません)。そのため、強制的に文字列にキャストする必要があります。したがって、最善の解決策は、明示的に自分でキャストすることです。

printf("%s", static_cast<char const *>(str));

そこにあるすべての例に必要なコードの量はわかりません。ほとんどの例では、カスタム文字列から std::string を構築し、それを出力してから std::string を削除する必要があるためです。 .

于 2012-08-22T10:44:12.693 に答える
3

できません(少なくともポータブルな方法では)。printfパラメータとして渡されたオブジェクトを見て%s、それを char 配列である として扱います。未定義の動作に遭遇します。また、に渡されるパラメーターprintfは、一種のタイプレスです。

なぜ printf(str) は問題ないのですか?

最初のパラメーターは型であり、const char*. 暗黙的なキャストは、オペレーターを介して行われます。残りのパラメーターは同じように動作しません。

cout代わりに使用し、オーバーロードしoperator << (ostream&, const CustomString&)ます。

これをしないでください:

ポータブルな方法ではできないと言いました。のようなクラスの場合

class CustomString
{
   char* str;
   //...
};

クラスがメモリ内でどのように表現されるかにより、それは機能する可能性があります。しかし、繰り返しますが、これはまだ未定義の動作です。

于 2012-08-22T09:04:02.913 に答える
1

を使用する必要がありますprintf("%s\n", str.c_str());%sは char 配列を期待していますが、CustomString別のオブジェクトを指定しました。関数を呼び出して、文字列から char 配列を取得する必要がありc_str()ます。

于 2012-08-22T09:03:58.980 に答える