0

私のプログラムは、単一のディレクトリを (非再帰的に) 反復処理し、そのディレクトリ内のすべてのファイルの名前を配列内に格納します。次に、プログラムの 2 番目の部分でその配列を使用し、各ファイルに関する情報を返します。ディレクトリを繰り返し処理でき、単一のファイルを処理できますが、プログラムの 2 つの部分を組み合わせるのに問題があります。これが私のコードです:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>

int getArraySize(char* arr[]);
int getArraySize(char* arr[]) {
  return sizeof(&arr);
}

char *filesArray[200];
int main (int argc, char* argv[])
{
  DIR *dir;
  struct dirent *ent;
  int filesCtr = 0;
  if ((dir = opendir ("/home/dshah/Documents/CECS 420/Project 3")) != NULL) {
    while ((ent = readdir (dir)) != NULL) {     /* print all the files and directories within directory */
      if (strcmp(ent->d_name, ".") == 0) {
        continue;
      } else if (strcmp(ent->d_name, "..") == 0) {
        continue;
      } else if (ent->d_type == 4) { // if a directory
        continue;
      } else {
        filesArray[filesCtr] = ent->d_name;
        printf("%s\n", filesArray[filesCtr]);
        filesCtr++;
      }
    }
    closedir (dir);
  } else {     /* could not open directory */
    perror ("Could not open directory");
  }

  int i;
  for (i = 0; i < getArraySize(filesArray); i++) {
    char* filename = filesArray[i];
    FILE *file = fopen (filename, "r");
    if (file != NULL) {
      char line [128]; /* or other suitable maximum line size */
      int ctr = 1;
      while (fgets(line, sizeof line, file) != NULL) { /* read a line */
        if (strstr(line, "is") != NULL) {
          printf("%s:%d:%s", filename, ctr, line);
        }
        ctr++;
      }
      fclose (file);
    } else {
      perror (filename); /* why didn't the file open? */
    }
  }
  return 0;
}

私が問題を抱えている行は次のとおりです。

char* filename = filesArray[i];

このコード行は正しいですか? filenameのような文字列に設定すると機能する"file.txt"ので、これも機能するはずではありませんprintf("n %s\n", filesArray[i]);か?filesArray[i]このコード行は文字列ですか?


編集:

ありがとう、それで問題は解決しました。もう 1 つ簡単な質問: にフル パスを追加しようとしています。

FILE *file = fopen (filename, "r");`

行に変更して

FILE *file = fopen (strcat("/home/dshah/Documents/CECS 420/Project 3/", filename), "r"); 

しかし、それは私にセグメンテーション違反を与えます。パスを指定しているだけなので、これでうまくいくのではないでしょうか?

4

1 に答える 1

1

配列を関数に渡すと、それはポインターに減衰するため、たとえば&arr実際にそのポインターへのポインターを取得すると、ポインターのサイズは元の配列のサイズではない可能性が高くなります。配列が実際に文字列である場合 (つまり、本当にそうである場合)、 を使用strlenして文字列の長さを取得できます (文字列終端文字は含まれません)。

あなたの場合、配列内にいくつの文字列があるかを示すカウンターが既にあるため、実際には関数は必要ありません:変数。getArraySizefilesArrayfilesCtr


readdirまた、返されたエントリのフィールドなどの関数を使用する場合、d_name実際には静的配列を指している可能性があるため、ポインターをコピーするだけではなく、文字列全体をコピーする必要があります。これは次のstrdup関数で行われます。

filesArray[filesCtr] = strdup(ent->d_name);

完了したら、freeこの文字列を使用する必要があることに注意してください。


ああ、たとえば、ディレクトリ エントリがサブディレクトリ ( ) であるかどうかを確認する場合など、コードで「マジック ナンバー」を使用しないでくださいent->d_type == 4。使用可能なマクロを使用します ( end->d_type == DT_DIR)。


最後d_nameに、エントリのフィールドにはreaddir、フル パスではなく、実際のファイル名のみが含まれます。したがって、完全なパスが必要な場合は、パスとファイル名を追加する必要があります。

于 2013-11-10T16:05:21.063 に答える