みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

UNIXの"find"コマンド同等のプログラム作成について

お世話になっております。
現在UNIXの"-type f"オプションのついた"find"コマンドと同等のプログラムをC言語で作ろうとしています。
つまりディレクトリ内のファイル(サブディレクトリ内のファイル含む、ディレクトリは除外)を全てフルパスで表示するプログラムです。
現在下記の関数を作成したのですがうまく動いてくれません。
どなたかご教授いただけないでしょうか。

【問題】
プログラム内の(**)前後で"dir1"が変更される。
(**)前:"/ディレクトリA/"
(**)後:"/ディレクトリA/ディレクトリA内のファイル1"
本当は"dir1"には:"/ディレクトリA/"のままであってほしいです。
"strcat"コマンドの仕様が影響しているのでしょうか。

int _find(char dir1[] , int k ,int l , int m )
{
DIR *dir ;
struct dirent *dp ;
struct stat statbuf ;
char txt[1000] ;
if ( m == 0 ) l++ ;
if ( (dir = opendir(dir1)) == NULL ){
printf("%s",dir1) ;
perror("opendir") ;
exit(1) ;
}
for( dp=readdir(dir) ; dp != NULL ; dp=readdir(dir) ){
if ( strcmp(dp->d_name,".") != 0 && strcmp(dp->d_name,"..") != 0 ){
/* ROOT_DIR名-にファイル名を付け加えて、フルパスにする */
strcpy( temp[k][l] , dir1) ;
strcat( temp[k][l] , "/" ) ;
strcat( temp[k][l] , dp->d_name ) ;  (**)
stat( temp[k][l] , &statbuf ) ;

if(S_ISDIR(statbuf.st_mode)){
l=_find(temp[k][l],k,l,1) ;
}else{
sort[k][l]=temp[k][l] ;
printf("temp[%d][%d]=%s\n",k,l,sort[k][l]);
printf( "dir5=%s\n",dir1) ;
l++ ;
}
}
}
closedir(dir) ;
return l ;
}

投稿日時 - 2009-08-26 15:37:37

QNo.5238352

すぐに回答ほしいです

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

以下のようにして下さい。
int _find(char dir1[] , int k ,int l , int m )
の中で、
(1)char temp_dir[256];を宣言する。
(2)
if(S_ISDIR(statbuf.st_mode)){
l=_find(temp[k][l],k,l,1) ;
}else{

l=_find(temp[k][l],k,l,1) ;を
strcpy(temp_dir,temp[k][l]);
l=_find(temp_dir,k,l,1) ;
上記の2行に置き換える。
temp[k][l]で渡されたのを、dir1で受け取りますが、
その後、temp[k][l]へファイル名をセットしているため、
dir1自体が同じ領域なので、結果的にdir1が破壊されたように見えます。これを防ぐには、一旦、temp_dirの格納し、それをdir1として渡します。

投稿日時 - 2009-08-26 20:59:04

補足

ご回答ありがとうございます。
ご教授頂いた修正方法で正常に動くようになりました。
ありがとうございました。

後学のため、追加でもう一点質問させて下さい。
ご指摘頂いた方法で正常に稼働したのですが、
dir1がおかしくなったのは(**)の箇所です。
(printf("%s",dir1)で確認しました。)

ご教授頂いたないようですと、以下の内容で変数b[]が壊れるのかと思ったのですが、確認したところ壊れませんでした。
char a[]="aiueo" ;
char b[]="oeuia" ;
strcpy(a[],b[]) ;
strcpy(b[],a[]) ;

おそらくtatsu99さんの"dir1自体が同じ領域なので"という箇所があまり理解できていないようです。
詳細に教えていただけませんでしょうか。

以上、よろしくお願いいたします。

投稿日時 - 2009-08-28 12:03:22

ANo.2

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.3

>おそらくtatsu99さんの"dir1自体が同じ領域なので"という箇所があまり理解できていないようです。
>詳細に教えていただけませんでしょうか。

あなたのソースでは
l=_find(temp[k][l],k,l,1) の形で、_findを呼び出しています。
それを、_findの関数では、_find(char dir1[],int k,int l,int m)
で受けています。そうすると、
dir1とtemp[k][l]は、実質的に同じアドレス(=同じ領域)を示しています。従って、
strcpy( temp[k][l] , dir1) ;
strcat( temp[k][l] , "/" ) ;
strcat( temp[k][l] , dp->d_name ) ;  (**)
のソースは
strcpy( dir1 , dir1) ;
strcat( dir1 , "/" ) ;
strcat( dir1 , dp->d_name ) ;  (**)
を実行しているのと同じ事になります。
従って、dir1の内容が変更されたように見えます。

投稿日時 - 2009-08-28 16:32:37

お礼

詳細な説明ありがとうございました。
おかげさまで理解できました。

投稿日時 - 2009-08-28 16:40:27

ANo.1

この関数を呼び出しているところも全て記述して下さい。
temp[k][l]などの記述から、tempの領域が、破壊されているように見えるが、提示されていないので、判断出来ません。
また、_findの各パラメータ(dir1,k,l,m)の意味を提示して下さい。
dir1は、ディレクトリ名というのは想像つきますが、ほかの
k,l,mの意味は何でしょうか。またこの値は、いくつから始まりますか?

投稿日時 - 2009-08-26 16:23:25

補足

ご指導いただきありがとうございます。
プログラム全体で実施しようとしているのは、テキストファイルより"ROOT_DIR ディレクトリ名"と書いてある箇所よりディレクトリ名を抜き出し、そのディレクトリに対してfindを実施します。
その出力結果のファイル名をtemp[k][l]に保存しようとしています。

で、k,l,mの値についてですが、以下の通りです。
k:ROOT_DIRで抜き出せるディレクトリの数
l:各ROOT_DIRで抜き出せるディレクトリ内のファイル数
m:ROOT_DIRで抜き出せるディレクトリをtemp[k][0]に保管するため、main関数から呼び出された場合のみ"l++"を実施するためのフラグ

main関数よりこの_findを呼び出す場合は以下のように実施いたします。
k=0 ;
while ( fscanf( fp1 , "%s" , dir1 ) != EOF ){
if ( strcmp(dir1,"ROOT_DIR") == 0 ){
l=0 ;
/* 抜き出した文字列がROOT_DIRの時,次の文字列をROOT_DIRとして読込む */
strcpy(temp[k][l],"ROOT_DIR ") ;
fscanf( fp1 , "%s" , dir1 ) ;
strcat( temp[k][l] , dir1 ) ;
sort[k][l]=temp[k][l] ;
l=_find(dir1,k,l,0) ;
k++ ;
}
}

またsortとtempは以下のようにグローバル関数として宣言しております。
char *sort[10][1000],temp[10][1000][254] ;

以上、よろしくお願いいたします。

投稿日時 - 2009-08-26 16:31:25

あなたにオススメの質問