
お世話になっております。
現在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 ;
}

No.2ベストアンサー
- 回答日時:
以下のようにして下さい。
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として渡します。
この回答への補足
ご回答ありがとうございます。
ご教授頂いた修正方法で正常に動くようになりました。
ありがとうございました。
後学のため、追加でもう一点質問させて下さい。
ご指摘頂いた方法で正常に稼働したのですが、
dir1がおかしくなったのは(**)の箇所です。
(printf("%s",dir1)で確認しました。)
ご教授頂いたないようですと、以下の内容で変数b[]が壊れるのかと思ったのですが、確認したところ壊れませんでした。
char a[]="aiueo" ;
char b[]="oeuia" ;
strcpy(a[],b[]) ;
strcpy(b[],a[]) ;
おそらくtatsu99さんの"dir1自体が同じ領域なので"という箇所があまり理解できていないようです。
詳細に教えていただけませんでしょうか。
以上、よろしくお願いいたします。

No.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の内容が変更されたように見えます。

No.1
- 回答日時:
この関数を呼び出しているところも全て記述して下さい。
temp[k][l]などの記述から、tempの領域が、破壊されているように見えるが、提示されていないので、判断出来ません。
また、_findの各パラメータ(dir1,k,l,m)の意味を提示して下さい。
dir1は、ディレクトリ名というのは想像つきますが、ほかの
k,l,mの意味は何でしょうか。またこの値は、いくつから始まりますか?
この回答への補足
ご指導いただきありがとうございます。
プログラム全体で実施しようとしているのは、テキストファイルより"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] ;
以上、よろしくお願いいたします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Windowsで複数のファイルを同じ...
-
パスから最後のディレクトリだ...
-
メールアドレスでメンバー認証
-
batファイルでrenameができませ...
-
vba dir の相対パス
-
C言語でファイル名を取得
-
readdir()で得られるファイル・...
-
エクセルVBA コードが同じでも...
-
ReadLineでの読み出し行を指定する
-
ExcelをCSV書き出す場合のシー...
-
Perlでログファイルからユーザ...
-
重複するデータを抽出できる秀...
-
MATLABのm-fileについて
-
Edge スクレイピング
-
window.open でのファイル指定方法
-
VBAでCSVファイルを途中行まで...
-
C言語でのファイルのデータ更...
-
close()で例外が投げられる理由
-
VBでファイル分割の方法
-
openした後、closeしないでプロ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Windowsで複数のファイルを同じ...
-
batファイルでrenameができませ...
-
vba dir の相対パス
-
パスから最後のディレクトリだ...
-
FindFirstFileとFindNextFileで...
-
readdir()で得られるファイル・...
-
ディレクトリー内のリスト出力...
-
ファイル名と更新日付の取得に...
-
C言語でファイル名を取得
-
ファイルの削除について
-
シェルでfind結果を文字列で比...
-
dos変数の%~dp0は powershellで...
-
フォルダに入っているファイル...
-
サーバー内にある指定した拡張...
-
CGIで日本語名ファイルのアップ...
-
find関数が1階層(カレントディ...
-
下のディレクトリ(3つ)に含ま...
-
ファイル名が日本語の物をダウ...
-
<>の意味が分かりません
-
makefileでファイルをコピー(...
おすすめ情報