ページ 1 / 1
このソースコードを直してほしいです。
Posted: 2012年3月24日(土) 21:00
by helloworld1853
Windows内のすべてのファイルを隠しファイル含めて検索し、
そのファイルの場所を返すプログラムを作りたいのですが
うまくいきません。
以下に僕が書いたソースコードを提示します。
このソースコードを直してほしいです。
まだWindowsプログラミングはやり始めたばかりなので、
ひどいソースコードです。
よろしくお願いします。
コード:
#define _CRT_SECURE_NO_DEPRECATE 1 // VisualC++2005 での警告抑制
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
static BOOL SearchFullPath(LPCTSTR pInFolder, LPCTSTR pTergetFile, LPTSTR pFullPath);
//LPCTSTR==const TCHAR *
//LPCTSTR==const TCHAR *
//LPTSTR==const CHAR *
int main(void)
{
TCHAR szFileName[MAX_PATH] = ("");//TCHAR==ASCII&UNICODE char
TCHAR szFullPath[MAX_PATH] = ("");//TCHAR==ASCII&UNICODE char
puts("ファイル名を入れてください:"); scanf_s("%s", szFileName, sizeof(szFileName) / sizeof(szFileName[0]));//sizeof==size
if (SearchFullPath("C:"), szFileName, szFullPath)
{
printf("%s", szFullPath);
}
return 0;
}
static BOOL SearchFullPath(LPCTSTR pInFolder, LPCTSTR pTergetFile, LPTSTR pFullPath)
//LPCTSTR==const TCHAR *
//LPCTSTR==const TCHAR *
//LPTSTR==const CHAR *
{
WIN32_FIND_DATA fd = {0};
HANDLE hFind = NULL;
TCHAR szSearchBuf[MAX_PATH];//TCHAR==ASCII&UNICODE char
BOOL bRet = FALSE;
if (!pInFolder || pInFolder[0] == '\0' || !pTergetFile || pTergetFile[0] == '\0' || !pFullPath)
{
return FALSE;
}
wsprintf(szSearchBuf, ("%s\\*.*"), pInFolder);//szSearchBuf=pInFolder japanese OK
hFind = FindFirstFile(szSearchBuf, &fd);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (lstrcmp(fd.cFileName, (".")) != 0 && lstrcmp(fd.cFileName, ("..")) != 0)
{
// . でも .. でもなければ
wsprintf(szSearchBuf, ("%s\\%s"), pInFolder, fd.cFileName);//
if (SearchFullPath(szSearchBuf, pTergetFile, pFullPath))
{
bRet = TRUE;
break;
}
}
}
else
{
if (lstrcmpi(fd.cFileName, pTergetFile) == 0)
{
// hit!
wsprintf(pFullPath, ("%s\\%s"), pInFolder, fd.cFileName);
bRet = TRUE;
break;
}
}
}
while (FindNextFile(hFind, &fd)!= INVALID_HANDLE_VALUE);
FindClose(hFind);
}
else
{
puts("ファイルが見つかりませんでした。");
}
return bRet;
}
Re: このソースコードを直してほしいです。
Posted: 2012年3月24日(土) 22:05
by パコネコ
私の勘違いでしたら申し訳ないのですが、
とりあえず何がうまくいかなかったのでしょうか?
起動自体はできましたでしょうか?
それとも自分の行いたいことどおりに動いてくれなかっただけでしょうか?
関数のほうはちゃんと読んでないのですが(私ではちゃんとした指摘ができないと思うので)、
とりあえず、引数がおかしなことになってるようです。
コード:
if (SearchFullPath("C:"), szFileName, szFullPath)
{
printf("%s", szFullPath);
}
少なくともここがこのままでは動かないと思うので、直してみてから実行してみて、
自分の行いたいことと、同じことができているのか確認してみてください。
Re: このソースコードを直してほしいです。
Posted: 2012年3月24日(土) 23:10
by helloworld1853
コード:
if (SearchFullPath(TEXT("C:"), szFileName, szFullPath))//TEXT マクロは、UNICODEが定義されているかどうかで文字列に L を付加します。
{
printf("%s", szFullPath);
}
こんな風に直してみました。
Visual Studio C++でコンパイルしています。
僕が期待している反応はまず
「ファイル名を入れてください:」 とでてくる
「cmd」と入力
コマンドプロンプトとその他のプログラムの場所が出てくる
しかし 実際は最初何も出てこず
cmdと入力すると
ファイルが見つかりませんでした。
ファイルが見つかりませんでした。
ファイルが見つかりませんでした。
・
・
・
と言う感じに「ファイルが見つかりませんでした。」が70個ぐらい出てきます。
夢と現実の差が・・・
原因がたくさんあるようです。
Re: このソースコードを直してほしいです。
Posted: 2012年3月25日(日) 01:35
by DVDM
> helloworld1853 さん
実行した訳ではないので、間違っていたら申し訳ないのですが
> と言う感じに「ファイルが見つかりませんでした。」が70個ぐらい出てきます。
このプログラムは本当に動作確認が出来ているのでしょうか。
上にある修正場所を加味した上でも、少なくとも実行できる状態ではないように見受けられます。
> while (FindNextFile(hFind, &fd)!= INVALID_HANDLE_VALUE);
FindFirstFile の戻り値は HANDLE 型であるためいいのですが、
FindNextFile の戻り値は BOOL 型(失敗すれば 0 を返したような気がします)であるのに対し、
HANDLE 型の値と比較しているのはなぜなんだろうと言う所が疑問でした。
また、「cmd」と入力とありますが
ファイル検索を行うプログラムですので、そういうフォルダがないと何も表示されないのではないでしょうか。
本当に確認ができているとすれば、とりあえずCドライブでなく、
もっと少ないファイルの場所で検索してみては如何でしょうか。
デバッガで追いやすくなると思います。
また、動作が確認出来ているプログラムを載せて頂ければ尚良いのではないかなと思います。
御検討下さいませ。
Re: このソースコードを直してほしいです。
Posted: 2012年3月25日(日) 09:30
by helloworld8153
コード:
while (FindNextFile(hFind, &fd)!= INVALID_HANDLE_VALUE);
の箇所を
コード:
while (FindNextFile(hFind, &fd));
に直した上でテストしました。
また、
コード:
if (SearchFullPath("C:"), szFileName, szFullPath)
の箇所を
コード:
if (SearchFullPath("C:\\User\\makurachan2008\\Desktop"), szFileName, szFullPath)
に変更し、C:\\User\\makurachan2008\\Desktopに test というフォルダを設置し、
その中に kami.c と iwill というフォルダを設置し 実験しました。
ビルドすると何も表示されず kami と入力すると
何も起こらず 続行するには何かキーを押してください。
と表示されます。
実は このソースコードは 知恵袋に質問して得られたもので、
あまりにも難しいものだったので (ただ、まったく理解できないというわけではないと思います。)
ちょっとしか修正できず
今に至ります。
そのため、
「動作が確認出来ているプログラムを載せて頂ければ尚良いのではないかなと思います。」
というご期待にそえられません。 すみません。
ちなみに僕がよく分からないという箇所はここらへんです。
コード:
if (lstrcmp(fd.cFileName, (".")) != 0 && lstrcmp(fd.cFileName, ("..")) != 0)
{
// . でも .. でもなければ
wsprintf(szSearchBuf, ("%s\\%s"), pInFolder, fd.cFileName);//
if (SearchFullPath(szSearchBuf, pTergetFile, pFullPath))
{
bRet = TRUE;
break;
}
}
Re: このソースコードを直してほしいです。
Posted: 2012年3月25日(日) 11:50
by パコネコ
helloworld8153 さんが書きました:
コード:
if (SearchFullPath("C:"), szFileName, szFullPath)
の箇所を
コード:
if (SearchFullPath("C:\\User\\makurachan2008\\Desktop"), szFileName, szFullPath)
に変更し、C:\\User\\makurachan2008\\Desktopに test というフォルダを設置し、
またまた同じところで恐縮ですが、
コード:
if ( SearchFullPath( "C:\\User\\makurachan2008\\Desktop" /*)*/ , szFileName, szFullPath)
ではないでしょうか?
SearchFullPath の引数は3つのはずなので一つ目でカッコを閉じてしまうのはまずいかと思われます。
( おそらく凡ミスですが、2度続けてということは、helloworld8153さんにとって気がつきにくいミスの可能性も高いので、注意しておいて損はナイト思います。 )
Re: このソースコードを直してほしいです。
Posted: 2012年3月25日(日) 12:09
by パコネコ
helloworld1853 さんが書きました:
ちなみに僕がよく分からないという箇所はここらへんです。
コード:
if (lstrcmp(fd.cFileName, (".")) != 0 && lstrcmp(fd.cFileName, ("..")) != 0)
{
// . でも .. でもなければ
wsprintf(szSearchBuf, ("%s\\%s"), pInFolder, fd.cFileName);//
if (SearchFullPath(szSearchBuf, pTergetFile, pFullPath))
{
bRet = TRUE;
break;
}
}
で、 同じところにのみでも悪いので一応、私の今調べた程度の付け焼刃の知識でですが、コメントを付け足せさていただきました。
コード:
// ----- - - -----
// PAKO_lstrcmp 引数の文字列が同じものかどうかを判断。
// PAKO_if( fd.cFileName != "." であり fd.cFileName != ".." ) ならば。
if (lstrcmp(fd.cFileName, (".")) != 0 && lstrcmp(fd.cFileName, ("..")) != 0)
{
// . でも .. でもなければ
// PAKO_wsprintf 引数1に引数2を元に作成した文字列を放り込む
// PAKO_szSearchBuf へ pInFolder//fd.cFileName を放り込む
wsprintf(szSearchBuf, ("%s\\%s"), pInFolder, fd.cFileName);//
// PAKO_ここは自分自身を呼び出します。(調べるための用語:復帰)
if (SearchFullPath(szSearchBuf, pTergetFile, pFullPath))
{
// PAKO_戻り値を TRUE にする。 つまりもう復帰の連鎖は止まる。・・・はず・・・
bRet = TRUE;
// PAKO_ループから抜け出します。
break;
}
}
それとよくわからない場所は一つ一つ関数等の意味を調べていくと分かっていく場合が多いです。
念のために言っておきますが、私の書いたコメントは私の主観的に書いたものが多いので、かならず自分で納得いかなかった部分は、
調べ直してください。( 自分にとってわかりやすく書いただけですので、正しく書いたわけではないですので。 )
参照:
lstrcmp
http://msdn.microsoft.com/ja-jp/library/cc410902.aspx
wsprintf
http://msdn.microsoft.com/ja-jp/library/cc364872.aspx
復帰
http://www.obihiro.ac.jp/~suzukim/masud ... ve_44.html
これらを踏まえたうえで修正してみてください。
またわからないところがあれば聞いてくだされば、答えてくださる方も沢山いると思いますので。
( 自分で調べもせず思考停止するのはもちろんなしですけど・・・ )
それでは、頑張ってください。
////////////////////////////////
追記
これまた念のため、修正と言いましたが別にこの箇所に問題があると言っているわけではないです。(;^ω^)
Re: このソースコードを直してほしいです。
Posted: 2012年3月25日(日) 17:05
by ISLe
質問者さんは"kami"と入力して"kami.c"を見付けたいのですか?
そうであればプログラムが正しい正しくない以前の問題ですけど。
提示されたコードは、大文字小文字の区別なしで全一致するファイル名を探すようになっています。
ちなみにコマンドプロンプトの実行ファイルのファイル名は"cmd.exe"ですし、スタートメニューにあるリンクのファイル名は"Command Prompt.lnk"(XP以前なら"コマンド プロンプト.lnk")です。
Re: このソースコードを直してほしいです。
Posted: 2012年3月25日(日) 21:57
by helloworld8153
なかなか動作しません。
根本的なところでミスをしている可能性があります。
なので テストプログラムを作ってみました。
いかがそれです。
コード:
#include<stdio.h>
#include<windows.h>
int main (void)
{
HANDLE hFind;
WIN32_FIND_DATA fd;
char moji[100];
puts("文字を入力してください"); scanf_s("%s",moji);
hFind = FindFirstFile((LPCWSTR)moji, &fd); /* 最初のファイル検索 */
if(hFind == INVALID_HANDLE_VALUE)/* 検索失敗? */
{
printf ("ファイル検索に失敗しました。 Get Last Error reports %d\n", GetLastError ());
return 0; // エラー終了
}
else
{
do
{
printf("ファイル名: %s\n", fd.cFileName);
if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
printf("ディレクトリ\n");
}
}while(FindNextFile(hFind, &fd)); //次のファイルを検索
}
FindClose(hFind);/* 検索終了 */
}
C:\\User\\makurachan\\Desktop\\test\\*.cと入力しましたが
ファイル検索に失敗しました。 Get Last Error reports 3
と出てきました。
なにか勘違いをしている気がします。
必死に検索してみましたが・・・その勘違いが分かりません(というよりもテストプログラムの情報を検索するだけで時間が・・・)
ご指摘お願いします。
Re: このソースコードを直してほしいです。
Posted: 2012年3月25日(日) 22:14
by beatle
FormatMessage関数を用いれば、GetLastError()で取得した整数を、エラーを示すメッセージに変換できるそうです。これを使って、エラー番号3に対応するエラーメッセージを表示させてみれば、詳しい原因が分かるかと思います。
Re: このソースコードを直してほしいです。
Posted: 2012年3月25日(日) 22:56
by helloworld8153
エラーコード3は
「指定されたパスが見つかりません。」
です。
フォルダは確かに存在するはずですが・・・
Re: このソースコードを直してほしいです。
Posted: 2012年3月26日(月) 00:42
by ISLe
まずシングルバイト文字列とワイド文字列の違いを理解すべきです。
シングルバイト文字列をワイド文字列にキャストしても文字コードが変換されるわけではありません。
と言ったところでシングルバイト文字とワイド文字が何なのかも分からないと思いますので、Visual C++のプロジェクトのプロパティを開いて、『構成プロパティ』→『全般』の『文字セット』を『マルチバイト文字を使用する』に変更するのが良いと思います。
検索できないファイル名が出てくるかもしれないですけど。
Re: このソースコードを直してほしいです。
Posted: 2012年3月26日(月) 07:14
by beatle
helloworld8153 さんが書きました:エラーコード3は
「指定されたパスが見つかりません。」
です。
フォルダは確かに存在するはずですが・・・
本当に存在しますか?入力したパスをエクスプローラに入れて、きちんと目的のフォルダが開けますか?
僕はWindows 7を使っています。Windows 7では
C:\\User\\username\\Desktop
は存在しませんが
C:\\Users\username\Desktop
は存在します。
Re: このソースコードを直してほしいです。
Posted: 2012年3月26日(月) 10:22
by かずま
helloworld8153 さんが書きました:コード:
char moji[100];
puts("文字を入力してください"); scanf_s("%s",moji);
scanf_s("%s",moji); は使い方を間違っています。
scanf_s("%s", moji, sizeof(moji));
または scanf("%99s", moji);
にしてみてください。
Re: このソースコードを直してほしいです。
Posted: 2012年3月26日(月) 16:54
by ISLe
プロジェクトの文字セットの設定に影響を受けないコードを書いてみました。
コード:
#include<windows.h>
#include<stdio.h>
int main(void)
{
HANDLE hFind;
WIN32_FIND_DATAA fd;
char path[_MAX_PATH+1];
puts("ファイルの検索パターン文字列を入力してください");
scanf_s("%s", path, _MAX_PATH);
hFind = FindFirstFileA(path, &fd);
if (hFind == INVALID_HANDLE_VALUE) {
return 1;
}
else {
do {
printf((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
"ディレクトリ" :
"ファイル"
);
printf("名: %s\n", fd.cFileName);
} while(FindNextFileA(hFind, &fd));
}
FindClose(hFind);
return 0;
}
Re: このソースコードを直してほしいです。
Posted: 2012年3月26日(月) 17:29
by helloworld1853
みなさまのおかげで
とうとう動作しました。
本当にありがとうございます。
今回を気に僕も
一歩前進した気がします。(気のせいかもしれませんが・・・)
C言語なんでも質問所 バンザイ!!!
Re: このソースコードを直してほしいです。
Posted: 2012年3月26日(月) 17:53
by ISLe
質問にあったのはサブディレクトリ以下も再帰的に検索するコードでしたけど…対応できたのでしょうか。