1

TCHARが取り組んでいる Visual C++ プロジェクトで使用しています。その定義を以下に示します。

#ifdef _UNICODE
    typedef wchar_t TCHAR;
#else
    typedef char TCHAR;
#endif

いくつかのデータを buffer に入れる必要がありますbuff:

char buff[size] = {0};  // how to declare the buffer size - what should be its value ?
sprintf(buff, "%s (ID: %i)", res->name(), res->id());

どこ:

name()戻り値TCHAR*

id()戻り値int

の値を計算する方法size- 実際のニーズに対する正確なバッファ容量 (Unicode が定義されていない場合は小さく、Unicode が定義されている場合は大きい) ? さらに、バッファ オーバーフローの可能性から身を守りたいのですが、どのような保護を使用すればよいですか?

さらに、ここではバッファを として宣言しましたchar。バッファを として宣言した場合int、サイズ値に違いはありますか (つまり、char として宣言された場合と比べて 4 倍小さくなります) ?

アップデート

Mats Peterssonの回答に部分的に基づいて私が思いついたのは次のとおりです。

    size_t len;
    const char *FORMAT;
#ifndef _UNICODE
    len = strlen((char*)res->name()); 
    FORMAT = "%s (ID: %i)";
#else
    len = wcslen(res->name());
    FORMAT = "%S (ID: %i)";
#endif    

    int size = 7 * sizeof(TCHAR) +                             /* place for characters inside format string */
               len * sizeof(TCHAR) +                           /* place for "name" characters */
               strlen(_itoa(id, ioatmp, 10)) * sizeof(TCHAR) + /* place for "id" digits */
               1 * sizeof(TCHAR);                              /* zero byte(s) string terminator */

    char *buff = new char[size];  /* buffer has to be declared dynamically on the heap,
                                   * because its exact size is not known at compilation time */
    sprintf(buff, FORMAT, name, id);
    delete[] buff;

それは正しい考えですか、それとも私は何かを見逃しましたか?

4

2 に答える 2

1

後ろから始めるには、buff常に である必要があります。charこれは、 によって格納されているためですsprintf

次に、res->name()ワイド文字 (Unicode) 文字列を返す場合、フォーマット文字列には を使用"%S"し、通常の ASCII には を使用する必要があります"%s"

ここで、バッファーに必要な長さを計算し、オーバーフローを回避します。のようなことをするのはそれほど難しいことではありません

      const TCHAR *nm = res->name();
      size_t len; 
#ifndef UNICODE
      len = strlen(nm); 
#else
      ... see below. 
#endif

次に、フォーマット文字列の定数として生成される正確な文字数とともに、数値の長さ (整数は 12 桁を超えることはできません) を推測します。

これは、標準の ASCII バリアントでは問題なく機能します。

ただし、ワイド char バリアントを使用すると、出力文字列で複数のバイトを使用できるため、より楽しくなります (たとえば、常にマルチバイト エンコーディングを必要とする漢字を書く場合)。1つの解決策は次のとおりです。

 len = snprintf(0, NULL, "%S", nm);

これで正しい番号が得られるはずです[私は思う]。かなり面倒な方法ですが、うまくいきます。別の方法でワイド文字列を「この文字列を格納するために必要なバイト数」に変換する簡単な方法があるかどうかはわかりません。

編集:UNICOD以外のveariantをサポートすることが重要かどうかを真剣に検討し、swprintf(...)代わりにすべてを使用するように変換します。長さはまだ必要ですが、wcslen(res->name())複雑な変換計算を必要とするのではなく、 の結果である必要があります。

于 2013-05-23T23:06:13.700 に答える
0
  1. 次を使用できます: snprintf / swnprintf。必要な文字数/文字数が返されます。
  2. ここchar buff[size] = {0};では、バッファの外に書いています。更新:私はそれを取り戻します-サイズが定数の場合、初期化を伴う単なる宣言です。
  3. これ"%s (ID: %i)"は次のように変更されます: "%s (ID: %d)"if last parameter is int.
于 2013-05-23T23:00:53.560 に答える