LPCWSTR型への変換

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
dic

LPCWSTR型への変換

#1

投稿記事 by dic » 15年前

ある関数を使うとき、引数に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]' に変換できません。
          この変換が可能なコンテキストはありません。

Blue

Re:LPCWSTR型への変換

#2

投稿記事 by Blue » 15年前

>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]
ということなら変換方法はいろいろあるのですけど。

dic

Re:LPCWSTR型への変換

#3

投稿記事 by dic » 15年前

色々調べてみました
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;
}
画像

dic

Re:LPCWSTR型への変換

#4

投稿記事 by dic » 15年前

解決押したのですが、またつまづいたので連続して質問させてください
#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使用です

dic

Re:LPCWSTR型への変換

#5

投稿記事 by dic » 15年前

#include "stdafx.h"
#include <Windows.h>

int _tmain(int argc, _TCHAR* argv[/url])
{
    TCHAR    *p;

    p = _wcsdup( _T("test") );

    free(p);

    return 0;
}
できました
失礼しました

softya

Re:LPCWSTR型への変換

#6

投稿記事 by softya » 15年前

問題が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;
}

softya

Re:LPCWSTR型への変換

#7

投稿記事 by softya » 15年前

>p = _wcsdup( _T("test") );
よく分からないからといって、_wcsdupで誤魔化すのは後で困ることになりますよ。

dic

Re:LPCWSTR型への変換

#8

投稿記事 by dic » 15年前

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
とありますが、統一というと、どういうことなのでしょうか?
画像

softya

Re:LPCWSTR型への変換

#9

投稿記事 by softya » 15年前

>とありますが、統一というと、どういうことなのでしょうか?

ユニコードでコンパイルするとOKだと思いますが、試しにマルチバイトにオプションを変えてみると分かります。
tchar.hは、そもそもどちらでもコンパイル出来るようにしたマクロですので。
そこにwchar限定の関数を書いてしまうのは、折角の切り替える仕組みを台無しにします。
だったら全部、wcharで書くべきだと思いますよ。

参照

http://msdn.microsoft.com/ja-jp/library ... 80%29.aspx

hoge

Re:LPCWSTR型への変換

#10

投稿記事 by hoge » 15年前

 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型への変換

#11

投稿記事 by たかぎ » 15年前

参考までに、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を部分的にサポートしたので、この辺はかなり複雑になりました。

dic

Re:LPCWSTR型への変換

#12

投稿記事 by dic » 15年前

詳しい解説をありがとうございます
時間がとれないので、コピーしてじっくり読ませてもらいます

dic

Re:LPCWSTR型への変換

#13

投稿記事 by dic » 15年前

だいぶ理解できました
ちょっと今の段階では統一しながらプログラムを組むのは難しいと思ってます

また、別の問題がおきました
#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型への変換

#14

投稿記事 by たいちう » 15年前

sprintfのセキュリティ強化版のTCHAR系をお望みですか?
でないなら、質問の意図が判りません。

_stprintf_s
http://msdn.microsoft.com/ja-jp/library ... 80%29.aspx

dic

Re:LPCWSTR型への変換

#15

投稿記事 by dic » 15年前

#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バイトの場合だと推測するのですが
この時に使用する関数がわかりません

dic

Re:LPCWSTR型への変換

#16

投稿記事 by dic » 15年前

swprintf_s関数ですね
わかりました
ありがとうございます

dic

Re:LPCWSTR型への変換

#17

投稿記事 by dic » 15年前

遅くなりましたが
VC++6では UNICODE 定義されていないので
CreateDirectryA
のように ...A
の方にマクロ展開しているようですね

VC++2010 では
CreateDirectoryW
に展開されますので、型が一致しないようです

閉鎖

“C言語何でも質問掲示板” へ戻る