• ベストアンサー

ファイル名の取得について

フォルダAとフォルダBに同じ名前のファイルが存在するか調べるPRGを考えています。 私の今までのやり方だと、フォルダからファイル名を一つづつ取り出し、その都度ファイル名が同じか判断していました。 しかし、この方法だとファイルが多いと時間が掛かると思われるため、最初にフォルダにあるファイル名をすべて取り出し、その後一つづつファイル名を比較しようと考えています。 この最初にファイル名をすべて取り出し、配列に代入する方法がよく判りません。 というか、配列に入れれば良いかもよく判りません。 ということで、簡単なコードなり、ヒントなり、参考になるサイトなり教えていただけるとありがたいです。

質問者が選んだベストアンサー

  • ベストアンサー
  • me_no_car
  • ベストアンサー率24% (22/90)
回答No.3

C言語では動的にメモリを確保する必要があります。 動的メモリ確保で検索するといろいろでてくる と思いますよ。 ファイル名を取得し配列に格納する サンプルソースのせておきます。 ちなみにディレクトリ名の取得はUNIX-Cです。 補足説明としては2回目以降はreallocでメモリ再確保 するのがポイントです。 連続したアドレスでメモリ確保してくるので別途アドレス を確保しておく必要もないし配列と同様に扱えます。 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <dirent.h> ---------------------------- int cnt=0; char DirPath[256]; char **filename; DIR *dir; struct dirent *dp; strcpy(DirPath,"ここに検索対象ディレクトリ"); dir = opendir(DirPath); while( (dp = readdir(dir)) != NULL ){ if( cnt == 0 ){ filename = (char **)malloc(sizeof(cnt + 1 )); } else{ filename = (char **)realloc(filename,sizeof(cnt + 1 )); } *(filename + cnt ) = (char *)malloc(sizeof(strlen(dp->d_name) + 1 )); *(filename + cnt) = dp->d_name; cnt++; } closedir(dir); -------------------------------------------

mk1234
質問者

お礼

回答ありがとうございます。 あとで知人から聞いたのですが、ファイル名の取得ぐらいなら2万件あってもたいしたことないので、mallocを使うより最大ファイル数を設定するほうが一般的らしいのですがそうなのでしょうか? (ケース バイ ケースなのでしょうが・・・)

その他の回答 (4)

  • muyoshid
  • ベストアンサー率72% (230/318)
回答No.5

こんにちわ。 全てのファイルを取り出して配列に格納しようとすると、 ファイルの数だけメモリを獲得する必要があるので 配列を使用しない方が良いと思いますょ。 具体的には、  1) フォルダA の下にあるファイル名を1つ取得  2) フォルダB に1) で取得したファイルがあると仮定    して、フルパスを作成  3) OpenFile 又は CreateFile で2) で作成した    フルパスをオープン  4) 正常にオープンできれば、同じ名前のファイルがある    と判断できる。  5) フォルダA の下のファイルを全て処理し終わるまで    1) 以下を繰り返し でどうでしょう?

mk1234
質問者

お礼

回答ありがとうございます。 なかなか面白そうなアイデアですね。 本当は、同じファイル名の捜索ではなく、同じファイル内容の捜索を行いたかったのですが、話を簡単にするためと、配列の扱いが知りたかったため最初の質問をしました。 有名な???AIKO for Win32と同じソフトを自作したかったのです。 今はDL出来なくなっているみたいですね。 昔はソースコードも公開されてると聞いたのですが、どなたか持っている人がいたら、送ってもらえませんかね。 こういうことは、作者に対し失礼なのでしょうか?

noname#30727
noname#30727
回答No.4

>私の今までのやり方だと、フォルダからファイル名を一つづつ取り出し、その都度ファイル名が同じか判断していました。 フォルダAから1つづつ取り出すときに "folderA\\*" など(Windows系の場合)で検索してますよね? 見つかったファイルが "filename.txt" だとしたら、すぐに "folderB\\filename.txt" でファイル検索すれば比較する手間もないですし、速度的にも気になるほどでもないと思います。 vector<string> と同等のものを作るのは大変ですが、機能限定ならそうでもないかも。 #include <stdio.h> #include <malloc.h> #include <string.h> typedef struct { int count; int limit; char **list; } svec; void init_svec(svec *v) { v->count = 0; v->limit = 0; v->list = NULL; } void add_svec(svec *v, const char *s) { char **temp; if (v->limit == 0) { v->limit = 1; v->list = (char**)malloc(sizeof(char*)); } else if (v->limit == v->count) { v->limit *= 2; temp = (char**)malloc(sizeof(char*) * v->limit); memcpy(temp, v->list, sizeof(char*) * v->count); free(v->list); v->list = temp; } v->list[v->count] = (char*)malloc(strlen(s) + 1); strcpy(v->list[v->count], s); v->count++; } void free_svec(svec *v) { int i; for (i = 0; i < v->count; i++) { free(v->list[i]); } if (v->limit) { free(v->list); } init_svec(v); } int main() { svec v; int i; init_svec(&v); add_svec(&v, "Black"); add_svec(&v, "Silver"); add_svec(&v, "Gray"); add_svec(&v, "White"); add_svec(&v, "Red"); add_svec(&v, "Purple"); for (i = 0; i < v.count; i++) { printf("%s\n", v.list[i]); } return 0; }

mk1234
質問者

お礼

回答ありがとうございます。 皆さんにいろいろ教えて頂いてこう言うのもなんですが、ファイル名を1つ取り出すたびに比較(あるいは検索)してもそう問題ないのかな?って気がしてきました。 なぜなら動的メモリの確保もそのつどメモリを確保し直すわけだし。 個人的に使うソフトのため、今回はこれで良しとさせてください。 もちろん、教えていただいたコードや考え方はしっかり勉強させていただきます。 ありがとうございました。

回答No.2

回答になっていません(多分)。 > 例えばキーボードから任意の個数の任意の長さの文字列を一つ入力するたびにエンターキーを押すような場合、 > 配列に文字列を格納するにはどのようにすれば良いのでしょう? 標準C++的には "配列なんか使いません" #include <iostream> #include <vector> #icnlude <string> using namespace std; int main() { vector<string> inputs; string line; while ( getline(cin, line) ) { inputs.push_back(line); } ... return 0; } > 必要配列の個数と必要文字列長さを入力時に動的に求める方法が知りたいです。 標準C++的には "クラスに考えてもらいます" # Cでどうするかは...他の方の回答を待ちます。

mk1234
質問者

お礼

すばやい回答ありがとうございます。 C言語で配列の場合はどうするのでしょう? よろしくお願いします。

回答No.1

#include <windows.h> #include <iostream> #include <string> #include <iterator> #include <set> #include <algorithm> template<typename OutIter> OutIter enumfiles(const std::string& path, OutIter result) { WIN32_FIND_DATA fd; HANDLE handle = FindFirstFile(path.c_str(), &fd); if ( handle == INVALID_HANDLE_VALUE ) return result; do { *result++ = fd.cFileName; } while ( FindNextFile(handle, &fd) ); FindClose(handle); return result; } // dir_a, dir_b の双方にあるファイル名を出力。 int main(int argc, char* argv[]) { std::set<std::string> fn1, fn2; enumfiles("d:\\dir_a\\*.*", std::inserter(fn1,fn1.end())); enumfiles("d:\\dir_b\\*.*", std::inserter(fn2,fn2.end())); std::set_intersection(fn1.begin(), fn1.end(), fn2.begin(), fn2.end(), std::ostream_iterator<std::string>(std::cout,"\n")); return 0; }

mk1234
質問者

お礼

epistemeさん 回答ありがとうございます。 私にとっては、ちょっと見慣れないコードが多いのであとでゆっくり理解します。

mk1234
質問者

補足

自分でも当然調べますが、もう少し基本的な方法として、 例えばキーボードから任意の個数の任意の長さの文字列を一つ入力するたびにエンターキーを押すような場合、配列に文字列を格納するにはどのようにすれば良いのでしょう? 必要配列の個数と必要文字列長さを入力時に動的に求める方法が知りたいです。 <補足> 多分判っている人にとっては、すごく基本的なことのような気がするのですが、私は今までこのようなことをやったことがないので”教えてあげましょう”と思われた方よろしくお願いします。

関連するQ&A