このソースコードを直してほしいです。

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

このソースコードを直してほしいです。

#1

投稿記事 by helloworld1853 » 8年前

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;
}

 

アバター
パコネコ
記事: 139
登録日時: 10年前
住所: 大阪

Re: このソースコードを直してほしいです。

#2

投稿記事 by パコネコ » 8年前

私の勘違いでしたら申し訳ないのですが、
とりあえず何がうまくいかなかったのでしょうか?
起動自体はできましたでしょうか?
それとも自分の行いたいことどおりに動いてくれなかっただけでしょうか?
関数のほうはちゃんと読んでないのですが(私ではちゃんとした指摘ができないと思うので)、
とりあえず、引数がおかしなことになってるようです。

コード:

    if (SearchFullPath("C:"), szFileName, szFullPath)
    {
        printf("%s", szFullPath);
    }
少なくともここがこのままでは動かないと思うので、直してみてから実行してみて、
自分の行いたいことと、同じことができているのか確認してみてください。
ニャン!!\(゜ロ\)(/ロ゜)/

helloworld1853

Re: このソースコードを直してほしいです。

#3

投稿記事 by helloworld1853 » 8年前

コード:

if (SearchFullPath(TEXT("C:"), szFileName, szFullPath))//TEXT マクロは、UNICODEが定義されているかどうかで文字列に L を付加します。
	{
        printf("%s", szFullPath);
	}
 
こんな風に直してみました。

Visual Studio C++でコンパイルしています。

僕が期待している反応はまず

「ファイル名を入れてください:」 とでてくる

「cmd」と入力

コマンドプロンプトとその他のプログラムの場所が出てくる

しかし 実際は最初何も出てこず

cmdと入力すると

ファイルが見つかりませんでした。
ファイルが見つかりませんでした。
ファイルが見つかりませんでした。
      ・
      ・
      ・
と言う感じに「ファイルが見つかりませんでした。」が70個ぐらい出てきます。

夢と現実の差が・・・

原因がたくさんあるようです。

アバター
DVDM
記事: 38
登録日時: 10年前
住所: 大阪
連絡を取る:

Re: このソースコードを直してほしいです。

#4

投稿記事 by DVDM » 8年前

> helloworld1853 さん
実行した訳ではないので、間違っていたら申し訳ないのですが
> と言う感じに「ファイルが見つかりませんでした。」が70個ぐらい出てきます。
このプログラムは本当に動作確認が出来ているのでしょうか。
上にある修正場所を加味した上でも、少なくとも実行できる状態ではないように見受けられます。

> while (FindNextFile(hFind, &fd)!= INVALID_HANDLE_VALUE);
FindFirstFile の戻り値は HANDLE 型であるためいいのですが、
FindNextFile の戻り値は BOOL 型(失敗すれば 0 を返したような気がします)であるのに対し、
HANDLE 型の値と比較しているのはなぜなんだろうと言う所が疑問でした。

また、「cmd」と入力とありますが
ファイル検索を行うプログラムですので、そういうフォルダがないと何も表示されないのではないでしょうか。

本当に確認ができているとすれば、とりあえずCドライブでなく、
もっと少ないファイルの場所で検索してみては如何でしょうか。
デバッガで追いやすくなると思います。
また、動作が確認出来ているプログラムを載せて頂ければ尚良いのではないかなと思います。
御検討下さいませ。

helloworld8153

Re: このソースコードを直してほしいです。

#5

投稿記事 by helloworld8153 » 8年前

コード:

 
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;
           }
}

アバター
パコネコ
記事: 139
登録日時: 10年前
住所: 大阪

Re: このソースコードを直してほしいです。

#6

投稿記事 by パコネコ » 8年前

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さんにとって気がつきにくいミスの可能性も高いので、注意しておいて損はナイト思います。 )
ニャン!!\(゜ロ\)(/ロ゜)/

アバター
パコネコ
記事: 139
登録日時: 10年前
住所: 大阪

Re: このソースコードを直してほしいです。

#7

投稿記事 by パコネコ » 8年前

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

これらを踏まえたうえで修正してみてください。
またわからないところがあれば聞いてくだされば、答えてくださる方も沢山いると思いますので。
( 自分で調べもせず思考停止するのはもちろんなしですけど・・・ )
それでは、頑張ってください。
////////////////////////////////
追記
これまた念のため、修正と言いましたが別にこの箇所に問題があると言っているわけではないです。(;^ω^)
ニャン!!\(゜ロ\)(/ロ゜)/

ISLe
記事: 2648
登録日時: 10年前
連絡を取る:

Re: このソースコードを直してほしいです。

#8

投稿記事 by ISLe » 8年前

質問者さんは"kami"と入力して"kami.c"を見付けたいのですか?
そうであればプログラムが正しい正しくない以前の問題ですけど。
提示されたコードは、大文字小文字の区別なしで全一致するファイル名を探すようになっています。

ちなみにコマンドプロンプトの実行ファイルのファイル名は"cmd.exe"ですし、スタートメニューにあるリンクのファイル名は"Command Prompt.lnk"(XP以前なら"コマンド プロンプト.lnk")です。

helloworld8153

Re: このソースコードを直してほしいです。

#9

投稿記事 by helloworld8153 » 8年前

なかなか動作しません。

根本的なところでミスをしている可能性があります。

なので テストプログラムを作ってみました。

いかがそれです。

コード:

#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

と出てきました。

なにか勘違いをしている気がします。

必死に検索してみましたが・・・その勘違いが分かりません(というよりもテストプログラムの情報を検索するだけで時間が・・・)

ご指摘お願いします。

beatle
記事: 1280
登録日時: 8年前
住所: 埼玉
連絡を取る:

Re: このソースコードを直してほしいです。

#10

投稿記事 by beatle » 8年前

FormatMessage関数を用いれば、GetLastError()で取得した整数を、エラーを示すメッセージに変換できるそうです。これを使って、エラー番号3に対応するエラーメッセージを表示させてみれば、詳しい原因が分かるかと思います。

helloworld8153

Re: このソースコードを直してほしいです。

#11

投稿記事 by helloworld8153 » 8年前

エラーコード3は

「指定されたパスが見つかりません。」

です。

フォルダは確かに存在するはずですが・・・

ISLe
記事: 2648
登録日時: 10年前
連絡を取る:

Re: このソースコードを直してほしいです。

#12

投稿記事 by ISLe » 8年前

まずシングルバイト文字列とワイド文字列の違いを理解すべきです。
シングルバイト文字列をワイド文字列にキャストしても文字コードが変換されるわけではありません。

と言ったところでシングルバイト文字とワイド文字が何なのかも分からないと思いますので、Visual C++のプロジェクトのプロパティを開いて、『構成プロパティ』→『全般』の『文字セット』を『マルチバイト文字を使用する』に変更するのが良いと思います。
検索できないファイル名が出てくるかもしれないですけど。

beatle
記事: 1280
登録日時: 8年前
住所: 埼玉
連絡を取る:

Re: このソースコードを直してほしいです。

#13

投稿記事 by beatle » 8年前

helloworld8153 さんが書きました:エラーコード3は

「指定されたパスが見つかりません。」

です。

フォルダは確かに存在するはずですが・・・
本当に存在しますか?入力したパスをエクスプローラに入れて、きちんと目的のフォルダが開けますか?
僕はWindows 7を使っています。Windows 7では
C:\\User\\username\\Desktop
は存在しませんが
C:\\Users\username\Desktop
は存在します。

かずま

Re: このソースコードを直してほしいです。

#14

投稿記事 by かずま » 8年前

helloworld8153 さんが書きました:

コード:

    char moji[100];

    puts("文字を入力してください"); scanf_s("%s",moji); 
scanf_s("%s",moji); は使い方を間違っています。
scanf_s("%s", moji, sizeof(moji));
または scanf("%99s", moji);
にしてみてください。

ISLe
記事: 2648
登録日時: 10年前
連絡を取る:

Re: このソースコードを直してほしいです。

#15

投稿記事 by ISLe » 8年前

プロジェクトの文字セットの設定に影響を受けないコードを書いてみました。

コード:

#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;
}

helloworld1853
記事: 181
登録日時: 8年前

Re: このソースコードを直してほしいです。

#16

投稿記事 by helloworld1853 » 8年前

みなさまのおかげで

とうとう動作しました。

本当にありがとうございます。

今回を気に僕も

一歩前進した気がします。(気のせいかもしれませんが・・・)

C言語なんでも質問所 バンザイ!!!

ISLe
記事: 2648
登録日時: 10年前
連絡を取る:

Re: このソースコードを直してほしいです。

#17

投稿記事 by ISLe » 8年前

質問にあったのはサブディレクトリ以下も再帰的に検索するコードでしたけど…対応できたのでしょうか。

閉鎖

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