ページ 1 / 1
LPCWSTR型への変換
Posted: 2010年4月29日(木) 15:50
by dic
ある関数を使うとき、引数にLPCWSTR型を使う関数があります
VC++6ではこれでコンパイル通ってたのですが
VC++2010 Express だとコンパイルが通らないです
char buf[1024]; の変数をどうやって LPCWSTR型に変換するのでしょうか?
というか、LPCWSTR型がよくわかってないです
#include "stdafx.h"
#include <Windows.h>
int _tmain(int argc, _TCHAR* argv[/url])
{
char buf[1024] = "test";
LPCWSTR buf2[1024];
buf2 = buf; // コンパイルエラー
return 0;
}
delete_ok.cpp(12): error C2440: '=' : 'char [1024]' から 'LPCWSTR [1024]' に変換できません。
この変換が可能なコンテキストはありません。
Re:LPCWSTR型への変換
Posted: 2010年4月29日(木) 16:25
by Blue
>VC++6ではこれでコンパイル通ってたのですが
本当に?
>LPCWSTR buf2[1024];
って(FARはとりあえず無視すると)
const wchar_t* buf2[1024];
ということなのですが、
>buf2 = buf;
から
const wchar_t**(const wchar_t*[1024]) に char*(char[1024]) の値を入れたいということなのでしょうか?
(cont char**(LPCSTR*) に char* 入れるのも無理だけど。)
char buf[1024]
から
wchar_t buf2[1024]
ということなら変換方法はいろいろあるのですけど。
Re:LPCWSTR型への変換
Posted: 2010年4月29日(木) 16:48
by dic
色々調べてみました
wchar_tも出てきましたが以下のようにして理解できました
#include "stdafx.h"
#include <Windows.h>
int _tmain(int argc, _TCHAR* argv[/url])
{
TCHAR buf[1024] = _T("test");
LPCWSTR buf2;
buf2 = buf;
return 0;
}

Re:LPCWSTR型への変換
Posted: 2010年4月29日(木) 17:14
by dic
解決押したのですが、またつまづいたので連続して質問させてください
#include "stdafx.h"
#include <Windows.h>
int _tmain(int argc, _TCHAR* argv[/url])
{
TCHAR buf[1024];
wcscpy_s( buf, sizeof(buf), _T("test") );
return 0;
}
とコンパイル通るところまではいったのですが、
wcscpy_s(.. のところで実行エラー(アクセス違反)が起きます
wcscpy_s()関数は、どのようにして使うのでしょうか?
サンプルがあると助かります
環境はVC++2010 Expressです
UNICODE使用です
Re:LPCWSTR型への変換
Posted: 2010年4月29日(木) 17:49
by dic
#include "stdafx.h"
#include <Windows.h>
int _tmain(int argc, _TCHAR* argv[/url])
{
TCHAR *p;
p = _wcsdup( _T("test") );
free(p);
return 0;
}
できました
失礼しました
Re:LPCWSTR型への変換
Posted: 2010年4月29日(木) 17:56
by softya
問題が2つほどあります。
まず、tcharを使って書くなら統一してください。
wcscpy_sでは無く、_tcscpy_sにしてください。これでユニコードとマルチバイト両対応になります。
あとは、wcscpy_s/_tcscpy_sの第2パラメータはバイト数ではなく文字数を入れてください。ユニコード時のTCHARは2バイトですので、sizeof(buf)は2048になってしまいます。
以下に修正したものを書いときますね。
#include <Windows.h>
#include <tchar.h>
#define TCHAR_SIZE(buf) (sizeof(buf)/sizeof(TCHAR))
int _tmain(int argc, _TCHAR* argv[/url])
{
TCHAR buf[1024];
_tcscpy_s( buf, TCHAR_SIZE(buf), _T("test") );
return 0;
}
Re:LPCWSTR型への変換
Posted: 2010年4月29日(木) 17:58
by softya
>p = _wcsdup( _T("test") );
よく分からないからといって、_wcsdupで誤魔化すのは後で困ることになりますよ。
Re:LPCWSTR型への変換
Posted: 2010年4月29日(木) 21:24
by dic
errno_t wcscpy_s(
wchar_t *strDestination,
size_t numberOfElements,
const wchar_t *strSource
);
wcscpy_s,_tcscpy_s の第2引数は、配列のサイズではなくて
要素数を渡すのですね
Elements は要素数ですね
安易にsizeof(buf); としてたので、実行時エラーがでてました
原因がわかりました
#include "stdafx.h"
#include <Windows.h>
int _tmain(int argc, _TCHAR* argv[/url])
{
TCHAR *p;
p = _wcsdup( _T("test") );
free(p);
TCHAR buf[1024];
_tcscpy_s( buf, (sizeof(buf)/sizeof(TCHAR)), _T("_tcscpy_s") );
wcscpy_s( buf, (sizeof(buf)/sizeof(TCHAR)), _T("wcscpy_s") );
return 0;
}
とやって、_tcscpy_s, wcscpy_s 両方とも動き、デバッカでも
bufに指定した文字が代入されていることが確認できました
あと、統一してくださいとあるんですが、
http://msdn.microsoft.com/ja-jp/library/td1esda9(VS.80).aspx
によると
tchar.hのルーチンは_tcscpy_s
_UNICODE が定義されている場合 wcscpy_s
とありますが、統一というと、どういうことなのでしょうか?

Re:LPCWSTR型への変換
Posted: 2010年4月29日(木) 21:40
by softya
>とありますが、統一というと、どういうことなのでしょうか?
ユニコードでコンパイルするとOKだと思いますが、試しにマルチバイトにオプションを変えてみると分かります。
tchar.hは、そもそもどちらでもコンパイル出来るようにしたマクロですので。
そこにwchar限定の関数を書いてしまうのは、折角の切り替える仕組みを台無しにします。
だったら全部、wcharで書くべきだと思いますよ。
参照
↓
http://msdn.microsoft.com/ja-jp/library ... 80%29.aspx
Re:LPCWSTR型への変換
Posted: 2010年4月29日(木) 23:01
by hoge
C/C+には「アスキー文字(半角英数等)」と「ワイド文字(unicodeによる文字・半角全角を含む)」
という二種類の文字型があります。w の付く文字変数や文字列操作関数などは皆、ワイド文字用です。
「char と wchar_t」
「strlen と wcslen」
「std::string と std::wstring」
「MessageBoxA と MessageBoxW」
と言った感じです。
基本的にこの両者は混在させるべきではありません。
char を使うなら全て char, wchar_t を使うなら全て wchar_t にしないと、
文字列処理関数が正常に動作しない可能性があります。
VC++ の TCHAR や LPTSTR などはtypedef、_tcscpy_s や_tcsclen などはマクロになっていて、
コンパイルスイッチでアスキー用の strlen と ワイド文字の wcslen などと切り変えられる
ようになっています。
tchar.h を見ると分かりますが、こういう感じになってます。
#ifdef _UNICODE
typedef wchar_t TCHAR;
#define _tcslen wcslen
#define _tcscpy_s wcscpy_s
#else
typedef char TCHAR;
#define _tcsclen strlen
#define _tcscpy_s strcpy_s
#endif
T系の型や関数を使用することで、二つの文字体系を _UNICODE 定義の有無で切り替えられます。
W系型や関数と、T系の型や関数をソースに混在させると、_UNICODEマクロが切り替わった
とき一部だけがその切り替えに対応されず、問題を起こす可能性があります。
問題を起こさないためには、
・T系だけで統一する。
・W系だけで統一する。
・アスキーだけで統一する。
のどれかにするのが良いという事になります。
ちなみに VisualStudioの場合、Win32プロジェクト等をウィザードを使って生成すると、
コンパイルオプションに _UNICODE が設定されますのでデフォルトではT系=W系になっています。
「空のプロジェクト」などでウィザードを使わなずプロジェクトを生成すると、_UNICODEは設定されず
T系=アスキーになります。
プロジェクトのプロパティ -> 構成プロパティ -> C/C++ -> コマンドライン を選択すると
コンパイルオプションが確認できます。
(「空のプロジェクト」の場合一度ビルドしてからでないとこの項目は出てこないかも)
補足として、
charは文字を表現する以外に、1バイトデータを表現するために使われることもあります。
この用途に限っては、TやWと関係なくいつでも使って問題ありません。
VCではBYTE という型も定義されているので、こちらを使うのも正しい選択です。

Re:LPCWSTR型への変換
Posted: 2010年4月30日(金) 00:46
by たかぎ
参考までに、Visual C++ 2010ということであれば...
扱うことができる文字の表現方法は少なくとも5種類あります。
1. ナロー文字。ASCIIなど、1バイトで表現出来る文字
2. 多バイト文字。シフトJISなど、2バイト以上で1文字を表す。
3. ワイド文字。wchar_t型を使用し、UTF-16で表現
4. char16_t型を使用し、UCS-2で表現
5. char32_t型を使用し、UCS-4で表現
C++0xを部分的にサポートしたので、この辺はかなり複雑になりました。
Re:LPCWSTR型への変換
Posted: 2010年4月30日(金) 21:53
by dic
詳しい解説をありがとうございます
時間がとれないので、コピーしてじっくり読ませてもらいます
Re:LPCWSTR型への変換
Posted: 2010年5月03日(月) 08:49
by dic
だいぶ理解できました
ちょっと今の段階では統一しながらプログラムを組むのは難しいと思ってます
また、別の問題がおきました
#include "stdafx.h"
#include <stdio.h>
#include <tchar.h>
int _tmain(int argc, _TCHAR* argv[/url])
{
int i;
TCHAR buf[1024];
for( i=0; i<10; i++ )
{
_tprintf_s( buf, _T("test - %d\n"), i );
_tprintf_s( buf );
}
return 0;
}
とプログラムを組んだのですが
buf に
test - 0
test - 1
test - 2
test - 3
test - 4
test - 5
test - 6
test - 7
test - 8
test - 9
と入れていきたいのですが、うまくいきません
どのように処理すればいいのでしょうか?
Re:LPCWSTR型への変換
Posted: 2010年5月03日(月) 09:09
by たいちう
sprintfのセキュリティ強化版のTCHAR系をお望みですか?
でないなら、質問の意図が判りません。
_stprintf_s
http://msdn.microsoft.com/ja-jp/library ... 80%29.aspx
Re:LPCWSTR型への変換
Posted: 2010年5月03日(月) 09:20
by dic
#include "stdafx.h"
#include <stdio.h>
#include <tchar.h>
int _tmain(int argc, _TCHAR* argv[/url])
{
int i;
// char型はコンパイルできる
char hoge[1024];
for( i=0; i<10; i++ )
{
sprintf( hoge, "hoge-%d\n", i );
printf( hoge );
}
// TCHAR型は代入できない
TCHAR buf[1024];
for( i=0; i<10; i++ )
{
_tprintf_s( buf, _T("test-%d\n"), i );
_tprintf_s( buf );
}
return 0;
}
とchar型への代入はできるのですが
TCHAR型の場合の代入方法がわからないのです
UNICODE定義しているので2バイトの場合だと推測するのですが
この時に使用する関数がわかりません
Re:LPCWSTR型への変換
Posted: 2010年5月03日(月) 09:25
by dic
swprintf_s関数ですね
わかりました
ありがとうございます
Re:LPCWSTR型への変換
Posted: 2010年5月06日(木) 19:40
by dic
遅くなりましたが
VC++6では UNICODE 定義されていないので
CreateDirectryA
のように ...A
の方にマクロ展開しているようですね
VC++2010 では
CreateDirectoryW
に展開されますので、型が一致しないようです