• 締切済み

フォルダ内検索

VC++6.0のMFCで開発しています。 フォルダをどろっぷしてフォルダ内のファイルを取り出すという プログラムです。 メインダイアログのクラス for(int p=0;p<__argc-1;i++) { CFileFind find; CString vv; vv=__argv[p]; CString Newstr=vv+_T("\\*.*"); if(find.FindFile(Newstr)){ int i=1; while(i){ if(__argv[p]==""){ return 0; } i=find.FindNextFile(); if(find.IsDots()){ continue; } if(find.IsDirectory()){ FolderDrop(find.GetFilePath()); } CString filename=vv+"\\"+find.GetFileName(); CString kakucho=GetKaku(filename); while((index3=m_listC.GetNextItem(index3,LVNI_ALL))!=-1){ indexstr=m_listC.GetItemText(index3,0); if(kakucho==indexstr){ kdlg.m_DirectoryFileNameArray.Add(filename); } } m_FilenameArray.Add(filename); m_FolderFileNumber++; } find.Close(); } } void CDragDrop6Dlg::FolderDrop(CString str) { CString kakucho; int i=m_listC.GetItemCount(); CString indexstr; CString filename2; CKakuninDlg kdlg; int p; int index3=-1; for(p=0;p<=c;p++){//ドロップしたファイルがディレクトリの場合 CFileFind find; CString Newstr=str+_T("\\*.*"); if(find.FindFile(Newstr)){ int i=1; while(i){  i=find.FindNextFile(); if(find.IsDots()){ continue; } if(find.IsDirectory()){ FolderDrop(find.GetFilePath()); } filename2=str+"\\"+find.GetFileName(); kakucho=GetKaku(filename2)//ファイルの拡張子を取り出す while((index3=m_listC.GetNextItem(index3,LVNI_ALL))!=-1){ indexstr=m_listC.GetItemText(index3,0); if(kakucho==indexstr){ kdlg.m_DirectoryFileNameArray.Add(filename2); } } m_FilenameArray.Add(filename2); m_FolderFileNumber++; } find.Close(); } } としてフォルダAの中にフォルダBが入っていてその中に入っているファイルCを取り出したいのです。 このプログラムではドロップしたファイルが 一番目のプログラムでフォルダA内の中身がファイルならfilenameに フォルダならBに潜り込む所まではいけました。 しかし実際に別ダイアログに取り出した全てのファイルの一覧を出すと A内のプログラムしか表示されません。どこがいけないのでしょうか?

みんなの回答

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

find.FindNextFile()で取得した名前がフォルダー(ディレクトリ)だった場合とファイルだった場合で動作がおかしくありませんか if ( find.IsDirectory() ) {   FileDrop(find.GetFilePath()); } filename2=str+"\\"+find.GetFileName(); kakucho=GetKaku(filename2)//ファイルの拡張子を取り出す while((index3=m_listC.GetNextItem(index3,LVNI_ALL))!=-1){ といった記述だと フォルダーの場合FileDropが再帰で呼ばれますが そこから帰った後 filename2 = ... の部分も実行してしまいますよ if ( find.IsDirectory() ) {   // フォルダーなので再帰   FileDrop(find.GetFilePath()); } else {   // ファイル名なのでリストに登録   filename2=str+"\\"+find.GetFileName();   kakucho=GetKaku(filename2)//ファイルの拡張子を取り出す   while((index3=m_listC.GetNextItem(index3,LVNI_ALL))!=-1){     // 中略   } } といった具合にしたほうがいいでしょう 期待する動作と異なる動作をしていそうな部分に ブレークポイントを設定してステップ実行するなどして見ましょう > for(p=0;p<=c;p++){//ドロップしたファイルがディレクトリの場合 で cは定義されていないようですが forループの中に入ってきますか? グローバル変数などで定義しているならDebug時には0xC0など特殊な初期化していませんの値になっています Release時には 0になってしまっている場合があります

okurinusi
質問者

補足

試してませんでした。ブレークポイントに関しては InitDialogがメインで行っているクラスですので 見れなかったきがします。

関連するQ&A

  • フォルダ検索

    VC++6.0のMFCでプログラムを組んでいます。 CFileFind find; CString Newstr=●●+_T("\\*.*"); if(find.FindFile(Newstr)) { int i=1; while(i) { if(●●==""){ return 0; } i=find.FindNextFile(); if(find.IsDots()){ continue; } if(find.IsDirectory()){ continue; } CString filename=●●+"\\"+find.GetFileName(); } } とすると●●フォルダの中のファイル名がfilenameに取得されます。 しかしもしフォルダの中にフォルダがある場合その中身も取得したいのですがどうすればいいのかわかりません。フォルダの中にフォルダが無くなるまで調べつづける予定です。

  • Debug Assertion Failed

    前回フォルダの中のフォルダの中のファイル検索について質問させていただきましたが再帰を使えというアドバイスをいただきVC++6.0のMFCダイアログベースにて 【InitDialog内】 if(int p=0; p<=argc;p++){ test(__argv[p]); } void ●Dlg::test(CString strFolder) { CFileFind find; CString Newstr=strFolder+_T("\\*.*"); if(find.FindFile(Newstr)) { int i=1; while(i) { if(strFolder==""){ return 0; } i=find.FindNextFile(); if(find.IsDots()){ continue; } if(find.IsDirectory()){ test(find.GetFilePath()); } CString filename=strFolder+"\\"+find.GetFileName(); m_Ary.Add(filename); find.close(); } } } ※m_Aryは●Dlgクラスのメンバ変数 CStringArray m_Ary; これを実行すると Debug Assertion Failedが出てきて デバッグを押すと BOOL CFileFind::FildNextFile() { →ASSERT(m_hContext !=NULL) →の所でひっかかってるようです。 どうすれば直りますか?

  • VC++、MFCでSDIでアプリ作成中

    現在、VC++、MFCでSDIでアプリ作成中です。 アイコン上にファイル(txtファイル)をドラッグ&ドロップしてメモ帳を起動したいです。 ただ、ドロップされたファイルはうまく読み込めるのですが、そのファイルを開く(表示)することができません。 ドロップされたファイルは、C○○View.cppで int C○○View::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; // TODO: この位置に固有の作成用コードを追加してください CStringArray argv; if( IsDropOnIcon( &argv, TRUE ) ){ int i; for( i = 0; i < argv.GetCount(); i++ ){ MessageBox( argv[ i ], "ドロップされたファイルは", MB_OK ); Read(argv[i]); } } } BOOL C○○View::IsDropOnIcon( CStringArray* argv, BOOL acceptFolder ) { CString cmdlin = ""; CString resToken; char* p; int startnum = 0; p = AfxGetApp()->m_lpCmdLine; if( strlen( p ) == 0 || p[ 0 ] == '-') return FALSE; cmdlin = p; resToken= cmdlin.Tokenize( "\"", startnum ); while( resToken != "" ){ if( resToken != " " && IsExist( resToken, acceptFolder ) ) argv->Add( resToken ); resToken= cmdlin.Tokenize( "\"", startnum ); }; return TRUE; } /* 引数で貰った文字列がファイルかどうかをチェック */ BOOL C○○View::IsExist( CString filepath, BOOL acceptFolder) { CFile fp; if( fp.Open( filepath, CFile::modeRead ) ){ fp.Close(); return TRUE; } return FALSE; } のargv[i]で取得しています。 これが、Read(arg[i])でうまく読み込めません。 ちなみにRead(CString filename)は正しく動くことは確認済みです。 Read(arg[i])を入れる場所がOnCreateがいけないとは思うのですが、どのタイミングで 読み込めばいいかがわかりません。 どなたか教えて頂けないでしょうか?

  • MFC、フォルダの中のファイルパス

    ダイアログベースにて、フォルダがドラッグアンドドロップされたら、フォルダの中のファイルのパスを一個ずつ取得したいのですが、どのようにしたらいいでしょうか。 void CDDDlg::OnDropFiles(HDROP hDropInfo) { char FileName[100]; int NameSize = sizeof(FileName); int FileNumber; CString str; int i; FileNumber = DragQueryFile(hDropInfo, 0xffffffff, FileName, NameSize); str.Format("ドロップされたファイルの数 =%d", FileNumber); AfxMessageBox(str); for(i=0; i<FileNumber; i++){ DragQueryFile(hDropInfo, i, FileName, NameSize); str.Format("第 %d 番目のファイル名 = %s", i, FileName); AfxMessageBox(str); } CDialog::OnDropFiles(hDropInfo); } のようにすると、フォルダのパスが出力されます。 例えば、testというフォルダの中にtest.txtがあり、testをドラッグアンドドロップしたら、test.txtのパスを取得したのですが・・・。 Visual Studio .NET2003を使用しており、まだ初心者ですがよろしくお願いします。

  • 構造体を動的に確保&解放

    度々お世話になってます。 構造体を動的に確保し、処理後メモリーリークが起こらないように解放したいです。 item を m_xcList.GetItemCount() 個、宣言したいです。 ご教授願いたいです。 ▼ソースの一部抜粋▼ void CFileListCreatorDlg::SameItemCheck(CString mySwitch) {  LVITEM  lvi;  int   index = 0;  UpdateData();  lvi.mask = LVIF_TEXT;  CString FullPathString;  CString myFileName;  index = 0;  while (index < CFileListCreatorDlg::m_xcList.GetItemCount()){   lvi.iItem = index;   lvi.iSubItem = 0;      lvi.pszText = const_cast<LPTSTR>(static_cast<LPCTSTR>(_T("")));   CFileListCreatorDlg::m_xcList.SetItem(&lvi);   index++;  }  //0:ファイル重複識別ナンバー 1:通し番号 2:フルパス 3:ファイル名 4:おおよそのデータサイズ 5:データサイズ 6:修正日 7:修正時間 8:備考欄 9:書式情報  //ファイル名、ファイル容量、修正日時により、重複チェック  struct item  {   CString RepetitionNum; //ファイル重複識別ナンバー   //int  Num;  //通し番号   CString FullPath; //ファイルパス   CString FileName; //ファイル名   //CString ApproximateByte; //おおよそのデータサイズ//バイト   CString AccurateByte;  //実際のデータサイズ//実バイト      //TCHAR ModifyDate[20];  //修正日   //CTime ModifyTime;  //修正時間      CString ModifyTime;  //修正時間      //TCHAR RemarksColumn[100];  //備考欄  };  //http://www-watt.mech.eng.osaka-u.ac.jp/~tasai/cp/lec1.html ← プログラム5を参考にしました。  struct item *array;  /* メモリの確保 */  array = (struct item*)malloc(sizeof(struct item)*(CFileListCreatorDlg::m_xcList.GetItemCount()-1));  if (array == NULL) {   StatusStringSet(_T("memory allocation error\r\n"),0,TRUE);   exit(EXIT_FAILURE);  }  //const int itemNum = sizeof item /sizeof array[0];  int i;  for (i = 0; i < CFileListCreatorDlg::m_xcList.GetItemCount(); i++) //初期化  {   array[i].RepetitionNum = _T(""); //ファイル重複識別ナンバー   array[i].FileName = _T(""); //ファイル名   array[i].AccurateByte = _T(""); //データサイズ   array[i].ModifyTime = _T(""); //修正時間  } int cc;  int dd;  cc = 1;  dd = 1;  if(mySwitch == _T("SameItemCheck_BY_FileName")){   //0:ファイル重複識別ナンバー 1:通し番号 2:フルパス 3:ファイル名 4:おおよそのデータサイズ 5:データサイズ 6:修正日 7:修正時間 8:備考欄 9:書式情報   StatusStringSet(_T("ファイル名により、重複チェック"),0,FALSE);   index = 0;   while (index < CFileListCreatorDlg::m_xcList.GetItemCount()){    array[index].RepetitionNum = _T("");    FullPathString = CFileListCreatorDlg::m_xcList.GetItemText(index,2);    if(FullPathString != _T("")){     array[index].FileName = FullPathToFileName(FullPathString);    }    for (dd = 0; dd <= index-1; dd++){     if (array[dd].FileName == array[index].FileName){      if (array[index].RepetitionNum != _T("")){       array[dd].RepetitionNum = array[index].RepetitionNum;       //" 重複番号欄に既に重複Noが、入っているとき"      }else{       //cc // " インクリメントcc"        CString str;        if (cc>=INT_MAX){         str = _T("MAX-Value");        }else{         str.Format(_T("%d"),cc);        }        array[index].RepetitionNum = const_cast<LPTSTR>(static_cast<LPCTSTR>(str));        if (array[dd].RepetitionNum != array[index].RepetitionNum){         cc++;        }      }      lvi.iItem = index;      lvi.iSubItem = 0;         lvi.pszText = const_cast<LPTSTR>(static_cast<LPCTSTR>(array[index].RepetitionNum));      CFileListCreatorDlg::m_xcList.SetItem(&lvi);      UpdateData(FALSE);            lvi.iItem = dd;      lvi.iSubItem = 0;         lvi.pszText = const_cast<LPTSTR>(static_cast<LPCTSTR>(array[index].RepetitionNum));      CFileListCreatorDlg::m_xcList.SetItem(&lvi);      UpdateData(FALSE);     }    }    index++;    UpdateData(FALSE);   }  }else if(mySwitch == _T("SameItemCheck_By_DataSize")){   //省略  } } ▲ソースの一部抜粋▲ コンパイルは通るのですが、実行時に↓のエラーがでます。 どこの部分ががおかしいのでしょうか??  ▼エラーメッセージ▼  FileListCreator.exe の 0x00f08ac1 でハンドルされていない例外が発生しました: 0xC0000005: 場所 0xcdcdcdbd を読み込み中にアクセス違反が発生しました。  void Empty() throw()  {   CStringData* pOldData = GetData();   IAtlStringMgr* pStringMgr = pOldData->pStringMgr;   if( pOldData->nDataLength == 0 )   {    return;   }   if( pOldData->IsLocked() )   {    // Don't reallocate a locked buffer that's shrinking    SetLength( 0 );   }   else   {    pOldData->Release();    CStringData* pNewData = pStringMgr->GetNilString();    Attach( pNewData );   }  }  ▲エラーメッセージ▲ 汎用的なコードをお教え願いたいです。宜しくお願いします。

  • C++の無限ループを解決してください

    アルゴリズムを勉強するときに以下のソースを書きました; void weighted_quick_union_algorithm() { static const int volume = 10; enum status { terminate_, union_, find_ }; string str; status sta; vector<int> system(volume, 0); vector<int> size(volume, 1); for (int index = 0; index != volume; ++index) { system[index] = index; } do { cout<<"cin"<<endl; cin >> str; for (string::size_type index = 0; index != str.size(); ++index) str[index] = toupper(str[index]); if (str == "UNION") sta = union_; else if (str == "FIND") sta = find_; else if (str == "TERMINATE") sta = terminate_; switch (sta) { case(0): { cout << str << endl; break; } case(1): { cout << str << sta << endl; int p(0), q(0), i(0), j(0); while (cin >> p) { cin >> q; for (i = p; i != system[i]; i = system[i]); for (j = q; j != system[j]; j = system[j]); if (i == j) continue; if (size[i] < size[j]) { system[i] = j; size[j] += size[i]; } else { system[j] = i; size[i] += size[j]; } cout << p << " - " << q << endl; } cout<<"break"<<endl; break; } case(2): { cout << str << sta << endl; break; } } } while (sta); } しかし unionを入力しあと ; でwhile(cin>>p)をブレイクしたら cin break UNION1 cin break Union1 で無限ループ 結構時間かかったが間違いがわかりません ちなみに最少は while(cin>>p>>q)と書いていましたが同じ結果です。 どうかお願いします

  • Aドライブのエラーを回避したいのですが、

    何度もすみません。 コンボボックスにドライブ一覧を取得しました。 そのコンボボックスを選択すると、 リストボックス1に、フォルダのパス名が表示されます。 リストボックス2に、ファイル名が表示されます。 CドライブやDドライブはいいのですが、 Aドライブのリムーバルドライブを選択すると エラーが表示されます。 エラーが表示される前に何とかしたいと思うのですが、 どうすればいいのかわかりません。 または、エラーを無視するでもいいです。 よろしくお願いします。 以下が、ドライブを選択した時のコンボボックスの関数です。 VisualStudio.NET WindowsXP MFC です。 void CFileViewView::OnCbnCloseupCombo1() { CString listtxt; comb.GetWindowText(listtxt); for(int i=list1.GetCount()-1;i>-1;i--) { list1.DeleteString(i); } for(int i=list2.GetCount()-1;i>-1;i--) { list2.DeleteString(i); } CFileFind find; listtxt=listtxt+"\\*";//? 「A:\*」などを指定する find.FindFile(listtxt,0); bool work=true; CString findtxt; while(work) { AfxMessageBox("OK");//表示される。 work=find.FindNextFile(); //? A:\などを指定する AfxMessageBox("OK2"); //表示されない。 if(find.IsDirectory() && !find.IsSystem() && !find.IsHidden()) { list1.AddString(find.GetFilePath()); } if(find.IsArchived() && !find.IsSystem() && !find.IsHidden()) { list2.AddString(find.GetFileName()); } } }

  • 文字列検索について

    下記のようなC++プログラムにおいて、Good Morning! の「r」以後が、 検索にひっかからないで、-1を返します。 何故なのか、どうぞよろしくお願いします。 -------------------------------------------------------- #include <iostream> #include <cstring> using namespace std; int flag = 0; // 該当文字があったかどうかのフラグ int strch_idx(const char* s, char c){ int temp; cout << strlen(s) << endl; for(int i=0; i<(signed)strlen(s); i++){ if(*s == c){ temp=i+1; // 配列のインデックスは0オリジンだが、インデックスは1からだから1+する flag = 1; break; } s++; } if(flag == 1) return temp; else return -1; } int main(){ const char* s = "Good Morning!"; int idx = strch_idx(s, 'i'); cout << "検索文字のインデックス:" << idx << endl; return 0; }

  • C++で乱数を重複しないように発生させる

    C++で乱数を重複しないように発生させるようにプログラムを変更しろと言われたのですが、できません。 教えていただきたいです。 #include<iostream> #include<cstdlib> #include<cstring> #include<ctime> using namespace std; int main() { int i,n; int *p; cout<<"何個記憶しますか?"<<endl; cin>>n; p=new int[n]; if(p==NULL){ cout<<"記憶域の確保に失敗しました。"<<endl; return 1; } srand((unsigned)time(NULL)); rand(); i=0; while(i<n){ p[i]=1+(int)((double)rand()/(RAND_MAX+1.0)*75); if(p[i]==p[i]) cout<<"p["<<i<<"]の値"<<p[i]<<endl; i++; } delete[] p; return 0; }

  • ファイルの置換

    ファイルを置換するプログラムを作ったのですがうまく置換してくれません。コードは以下のように書きました。(コンパイラは出来ました) #include <stdio.h> #include <stdlib.h> #include <string.h> #define FALSE 0 #define TRUE 1 main() { FILE *fp; char filename[256]; FILE *outfp; char outfilename[256]; char key[128]; char str[128]; char c; int p; int keylen; int i=0 ; int search=FALSE; int count =0; printf(" enter filename"); scanf("%s",filename); printf("seach word"); scanf("%s",key); keylen=strlen(key); printf("change word"); scanf("%s",str); if((fp=fopen(filename,"r"))==NULL) { printf("file open error"); exit(1); } strcpy(outfilename,filename); strcat(outfilename,"_"); if((outfp=fopen(outfilename,"w"))==NULL) { printf("file open error"); exit(1); } while((c=fgetc(fp))!=EOF) { if(search) { if(c != key[i]) { search=FALSE; for(p=0;p<i;p++) { fputc(key[p],outfp); } fputc(c,outfp); i=0; } else{i++;} } else { if(c==key[i]) {search=TRUE;i++;} else {fputc(c,outfp);} } if (keylen==i) { count++; fputs(str,outfp); search=FALSE; i=0; } } fclose(fp); fclose(outfp); printf("apperance number %d\n",count); return 0; } どこか間違っていますか?教えてください。

専門家に質問してみよう