教えて! goo のコンテンツに対する取り組みについて

ある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);
}

gooドクター

A 回答 (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用の関数を全体的に使ったほうが良いでしょうけど。
    • good
    • 0
この回答へのお礼

%sを%Sにしたら改善しました。ありがとうございました。

お礼日時:2009/05/21 10:55

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文字列を使う』を『マルチバイト文字セットを使う』に変更する
といった対処をしましょう
    • good
    • 0
この回答へのお礼

みなさんくわしいですね、どこで勉強したんですか?

お礼日時:2009/05/21 10:56

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

gooドクター

人気Q&Aランキング