- ベストアンサー
[C++]WCHARの1文字目しか表示できない
あるWebサイトによると以下のプログラムでディレクトリ内の ファイル一覧を表示できるそうだ。たしかにファイル一覧を 表示できた。しかし、わたしの電子計算機上では、 ファイル名の1文字目しか表示できない。 なおfd.cFileNameはWCHARという配列のようだ。fd.cFileName[2]のように 文字位置を指定すれば、1文字目以降を取得できる。 Windows XP SP3 Visual C++ 2008 Express Edition ーーーーーーーーーーーーーーーーーーーーーーーーー #include <stdio.h> #include <string> #include <iostream> #include "windows.h" using namespace std; int main(int argc, char *argv[]) { HANDLE hFind; WIN32_FIND_DATA fd; FILETIME ft; SYSTEMTIME st; wstring FName; FName = L"*.*"; /* 最初のファイル検索 */ hFind = FindFirstFile(FName.c_str(), &fd); /* 検索失敗? */ if(hFind == INVALID_HANDLE_VALUE) { printf("検索失敗\n"); return(0); /******** エラー終了 ********/ } while(FindNextFile(hFind, &fd)){ FileTimeToLocalFileTime(&fd.ftLastWriteTime, &ft); FileTimeToSystemTime(&ft, &st); printf("ファイル名: %s", fd.cFileName); if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { printf("(ディレクトリ)"); } printf("\n短いファイル名: %s\n", fd.cAlternateFileName); printf("ファイルサイズ: %d\n", fd.nFileSizeLow); printf("更新日: %04d/%02d/%02d %02d:%02d:%02d\n\n",st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); } /* 検索終了 */ FindClose(hFind); return(0); }
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
printfで%sを指定したばあい、char型配列に格納された文字列を表示することになります。 WCHAR(wchar_t)型配列にUnicodeで格納された文字列である場合、 Unicodeは2バイトで1文字であるため、たとえば、「ABC」という文字列である場合 0x0041 0x0042 0x0043 0x0000 という文字コード配列になります。 これを無理やりchar型の配列としてみなすようにすると、 0x41 0x00 0x42 0x00 0x43 0x00 0x00 0x00 というようなShift_JISの文字コードの配列になります。 C言語の文字列の終端は'\0'が出てくるまでということなので、 最初の1文字で終わりになってしまうわけです。 回避策としては、 ・printfを使用せず、wchar_tに対応したwprintfを使用する。(setlocaleが必要) ・%sではなく%Sを使用する。 のどちらかでしょうか。 もっとも、Win32 APIを使う以上、文字列は大抵TCHARで扱うことが多いので、 TCHAR用の関数を全体的に使ったほうが良いでしょうけど。
その他の回答 (1)
- redfox63
- ベストアンサー率71% (1325/1856)
printfは基準がMBCS(マルチバイト)になっています つまり0x00が文字列の終端として使われ、文字もバイト単位でアクセスされます L"AB"の場合 ワイド文字ですと 0x41 0x00 0x42 0x00 0x00 0x00 といった並びになるので最初の Aしか出力されません ワイド文字版の wprintfですと文字も16ビット単位でアクセスされるので "AB"が出力されます これを回避するのであれば ヘッダーの tchar.h をインクリュードして WIDE文字、MBCS文字共通のマクロでコーディングします 文字列リテラルは _T("ABC") または _TEXT("TEXT") printfの場合 _tprintf といった具合にして見ましょう マルチバイトモードで一時的にワイド文字列を出力したいなら %sではなく %S で 書式指定しましょう また、VC++プロジェクトの設定の文字セットを『Unicode文字列を使う』を『マルチバイト文字セットを使う』に変更する といった対処をしましょう
お礼
みなさんくわしいですね、どこで勉強したんですか?
お礼
%sを%Sにしたら改善しました。ありがとうございました。