
http://msdn.microsoft.com/ja-jp/library/td1esda9 …
を見て、たとえば以下のような関数を書いたとします。
TCHAR* fn;
void OMG(LPCTSTR c){
int bytes( ( _tcslen(c) + 1 )*sizeof(TCHAR) );
if ( fn = (TCHAR*)malloc( bytes ) ) _tcscpy_s( fn, bytes, c ); //実行しないでください
else return;
/* fnを使用 */
free(fn); fn=0;
}
これ、マルチバイトだと正常に出来るのですが
なぜかUnicodeだと落ちてしまいました。
第2引数の説明は
コピー先の文字列バッファのサイズ。
<英語版でも>
Size of the destination string buffer.
となっていますが、その上に
numberOfElements
って書いてあるのでまさかと思い
サイズではなく文字数に変えたら、どうも正常に動作するようになったようです。
とくに_sがつく関数は文字数だったりバッファサイズだったりまちまちな感がもともとあるのに、しかも
こういうところでこういうことがあると厳しいものがあるのですが
これは本当に誤植なのでしょうか?
また、かなり稀なケースであり本当に誤植だとしたら、MSDNの他の文字列操作関数には記述の誤りがあるものはありますか?
No.2ベストアンサー
- 回答日時:
C++のtemplateを使ったstrcpy_s,wcscpy_sは
template <size_t size>
errno_t strcpy_s(
char (&strDestination)[size],
const char *strSource
); // C++ only
template <size_t size>
errno_t wcscpy_s(
wchar_t (&strDestination)[size],
const wchar_t *strSource
); // C++ only
となっています。
これをみると、sizeは「配列数」ということになります。
ですので、「numberOfElements」のさす意味そのもので「要素の数」(≠文字数)という解釈になります。
ちなみに、Unicodeでも1文字2バイトとは限りませんので
一概に文字数ともいえません。
(サロゲート で検索してみてください。)
>TCHAR c[100];
>
>if ( fn = (TCHAR*)malloc( sizeof c ) ) _tcscpy_s( fn, >sizeof(c)/sizeof(TCHAR), c );
>
>とか
>_tcscpy_s( fn, 100, c );
まぁ、結果的にあっていますが、fnに格納するときにバッファが足りているかをみるのをcを使うのはよろしくないかなと。
>int len( _tcslen(c) + 1 );
>if ( fn = (TCHAR*)malloc( len*sizeof(TCHAR) ) ) _tcscpy_s( fn, len, c );
のほうがよいですね。
まぁ、cに格納されている文字列を新しい領域をmallocしてコピーするのであれば、_tcsdupで
TCHAR* fn = _tcsdup(c);
と記述できます。
http://msdn.microsoft.com/ja-jp/library/y471khhc …
>Unicodeでも1文字2バイトとは限りません
そうだったのですか
調べてみたら色々な方式があるようですね。
しかし、いずれにしても
>>int len( _tcslen(c) + 1 );
>>if ( fn = (TCHAR*)malloc( len*sizeof(TCHAR) ) ) _tcscpy_s( fn, len, c );
>のほうがよいですね。
ということは、sizeof(TCHAR)を使えばマルチバイトのバイト数と同じように判定できる、と考えて良いということですね。
>TCHAR* fn = _tcsdup(c);
こんな便利な関数があったのですね
色々と詳しいところありがとうございます♪
No.1
- 回答日時:
UNICODEでは1文字が何バイトになるか…という辺りが規定できないのでしょう。
Win32APIでも、ANSI版は「バイト数」、UNICODE版は「文字数」で扱うものが多いです。
GetModuleFileName()など…
>nSize
>[入力]lpFilename バッファのサイズを、TCHAR 単位で指定します。パス名とファイル名がこのバッファより大きかった場合、この関数は文字列を切り捨てます。
「TCHAR 単位」というのが、バイト数ではない…というコトになります。
ありがとうございます。
TCHAR単位ってちゃんと書いてあればどうコードを書けばいいかちゃんと判断出来ますが
http://msdn.microsoft.com/ja-jp/library/ce3zzk1k …
http://msdn.microsoft.com/ja-jp/library/eywx8zcx …
このへんは文字数って書いてあるのでこれでも判断できます
http://msdn.microsoft.com/ja-jp/library/8e46eyt7 …
これも1 バイト文字またはワイド文字の数と書いてあるので(ANSIでは1バイト文字の数なのかバイト数なのかといえば後者のような気がしますが(まだ試していません))
少なくともUnicodeではバイト数ではないと判断できます。
う~ん
両方対応するように一気に手直しした際、その中で
_tcscpy_s先に見ちゃったから
まちまちだと思ってしまったのかもしれませんが
実際には、おっしゃる通り
表記が一律でないだけで(ほぼ、あるいは全部かも)
>ANSI版は「バイト数」、UNICODE版は「文字数」
のような感じがしますね。
表記上そう読めなかったら検証してみることにします。
現状はUnicodeは2バイトのはずですし
上記コードは
int len( _tcslen(c) + 1 );
if ( fn = (TCHAR*)malloc( len*sizeof(TCHAR) ) ) _tcscpy_s( fn, len, c );
こういった具合に直しておけば問題はないはず。
また、こういう場合でも
TCHAR c[100];
if ( fn = (TCHAR*)malloc( sizeof c ) ) _tcscpy_s( fn, sizeof(c)/sizeof(TCHAR), c );
とか
_tcscpy_s( fn, 100, c );
といった具合にすればOK
と、思うのですが、コード側の対処法としてはこんな感じの考え方でOKでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- 数学 関数列の収束について 次の問題を教えて欲しいです。 区間[0,1) の関数列fnと関数f(x)につい 1 2022/06/01 08:33
- Visual Basic(VBA) 【マクロ】フォルダにファイルが1つも無い時に、ファイルがありませんとメッセージを表示する 4 2022/08/28 08:48
- Excel(エクセル) 1つのファイルを3つのフォルダにファイル名を【明日の日付】にして、コピーをしたい 2 2022/12/21 17:43
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- Excel(エクセル) 【マクロ】フォルダAからダBへファイルを、ファイルの更新日時の条件で、1つづつ移動するには? 3 2022/08/25 09:56
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# leetcode 155 minstack 1 2022/05/07 16:43
- Excel(エクセル) マクロのコードを、少しでも削って短くしたい 3 2022/08/30 07:46
このQ&Aを見た人はこんなQ&Aも見ています
-
CString から LPCTSTRの型に変換
C言語・C++・C#
-
CStringからchar*への型変換について教えてください。
C言語・C++・C#
-
strncpyと_tcsncpy_sのヌルの扱いが違う点
C言語・C++・C#
-
-
4
CStringをwchar_tに変換したい
C言語・C++・C#
-
5
c++std::string型をTCHARに変換したい!
C言語・C++・C#
-
6
CStringのFindで文字列検索を行いたいのですが
C言語・C++・C#
-
7
ダイアログ表示時にチェックボックスにチェックされている状態にするには?
C言語・C++・C#
-
8
VC++スレッドの正しい終了のさせかた
C言語・C++・C#
-
9
エディットボックスの入力制限について
C言語・C++・C#
-
10
エディットコントロールでEnter押した時の動作
C言語・C++・C#
-
11
charからLPTSTRへの変換方法
C言語・C++・C#
-
12
メモリリークの件
C言語・C++・C#
-
13
WaitForSingleObjectの使い方について
C言語・C++・C#
-
14
画面を強制的に再描画させる方法
C言語・C++・C#
-
15
CString型の文字列連結について
C言語・C++・C#
-
16
ラベル(スタティックテキスト)内での改行。
C言語・C++・C#
-
17
LPCWSTRとchar
C言語・C++・C#
-
18
CStringの文字列検索&抜き出しについて
C言語・C++・C#
-
19
コンボボックスでデフォルト値の設定
C言語・C++・C#
-
20
コンボボックスのドロップダウンリストが表示されない
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
プログラム問題・・・
-
WSH(VBS)でJSONの文字列を読み...
-
C++で入力した文字列から数字を...
-
sprintf関数での文字列変換につ...
-
nullと""、\\0とEOFの違いにつ...
-
for文での配列の指定について(...
-
構造体→文字列→構造体 をする方法
-
バイナリファイル中の日本語文...
-
CSVファイルの「”」について
-
文字コードによる表記
-
C言語の問題です。
-
_tcscpy_s(wcscpy_s)の第二引数...
-
16進数を2文字ずつ配列に格納し...
-
文字の桁を増やす方法。
-
シリアル通信で0x00を送信した...
-
c#で他のアプリの文字入力フォ...
-
X='A'とX="A"の違いは
-
VB6.0でのバイナリデータの扱い...
-
プログラムによく出てくるst...
-
CStringからchar*への型変換に...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
TCL言語で文字列検索方法を教え...
-
C#でstringをポインタとして渡す
-
C++で入力した文字列から数字を...
-
nullと""、\\0とEOFの違いにつ...
-
c#で他のアプリの文字入力フォ...
-
WSH(VBS)でJSONの文字列を読み...
-
バイナリファイル中の日本語文...
-
シリアル通信で0x00を送信した...
-
%dなどの違い
-
16進数を2文字ずつ配列に格納し...
-
VB6.0でのバイナリデータの扱い...
-
C++で文字列の右端から特定の文...
-
構造体→文字列→構造体 をする方法
-
_tcscpy_s(wcscpy_s)の第二引数...
-
char型配列の最大要素数
-
VBA-DLLの引数受け渡しについて
-
binaryに対して正規表現を適用...
-
数字の入った配列をファイルへ...
-
C言語の課題で困っています;
-
プログラムによく出てくるst...
おすすめ情報