回答編集履歴

4

コード修正

2022/11/02 02:02

投稿

jimbe
jimbe

スコア12696

test CHANGED
@@ -32,7 +32,7 @@
32
32
  void freeStack(Stack *stack) {
33
33
  if(stack != NULL) {
34
34
  if(stack->entries != NULL) {
35
- for(int i=0; i<stack->top; i++) free(stack->entries[i]);
35
+ for(int i=0; i<stack->top; i++) freeEntry(stack->entries[i]);
36
36
  free(stack->entries);
37
37
  }
38
38
  free(stack);

3

変数名等修正

2022/11/01 08:47

投稿

jimbe
jimbe

スコア12696

test CHANGED
@@ -12,9 +12,6 @@
12
12
  #include <string.h>
13
13
  #include <dirent.h>
14
14
  #include <sys/stat.h>
15
-
16
- typedef struct stat Stat;
17
- typedef struct dirent DirEnt;
18
15
 
19
16
  typedef struct {
20
17
  char path[512];
@@ -76,7 +73,7 @@
76
73
  }
77
74
 
78
75
  int isDirectory(char *path) {
79
- Stat st;
76
+ struct stat st;
80
77
  if(stat(path, &st)) return 0; //false
81
78
  return (st.st_mode & S_IFMT) == S_IFDIR;
82
79
  }
@@ -90,25 +87,25 @@
90
87
  Stack *stack = allocStack();
91
88
  pushStack(stack, allocEntry(path));
92
89
 
93
- char work[1024];
94
- for(StackEntry *entry; (entry=popStack(stack)) != NULL; ) {
90
+ for(StackEntry *parent; (parent=popStack(stack)) != NULL; freeEntry(parent)) {
95
- printf("entry->path=%s\n", entry->path);
91
+ printf("parent->path=%s\n", parent->path);
96
- DIR *dir = opendir(entry->path);
92
+ DIR *dir = opendir(parent->path);
97
93
 
98
- for(DirEnt *de; (de=readdir(dir)) != NULL; ) {
94
+ for(struct dirent *de; (de=readdir(dir)) != NULL; ) {
99
95
  printf("de->d_name=%s\n", de->d_name);
100
96
  if(de->d_name[0] == '.') continue; //"."(カレント),".."(親)および'.'で始まる隠しファイルは無視
101
97
 
98
+ char childpath[1024];
102
- sprintf(work, "%s\\%s", entry->path, de->d_name);
99
+ sprintf(childpath, "%s\\%s", parent->path, de->d_name);
103
- if(isDirectory(work)) {
100
+ if(isDirectory(childpath)) {
104
- printf("directory: %s\n", work);
101
+ printf("directory: %s\n", childpath);
105
- pushStack(stack, allocEntry(work));
102
+ pushStack(stack, allocEntry(childpath));
106
103
  } else {
107
- printf("file: %s\n", work);
104
+ printf("file: %s\n", childpath);
108
105
  }
109
106
  }
107
+
110
108
  closedir(dir);
111
- freeEntry(entry);
112
109
  }
113
110
 
114
111
  freeStack(stack);
@@ -128,7 +125,7 @@
128
125
  実行結果
129
126
  ```plain
130
127
  > printdir F:\teratail\teratail\aaa
131
- entry->path=F:\teratail\teratail\aaa
128
+ parent->path=F:\teratail\teratail\aaa
132
129
  de->d_name=.
133
130
  de->d_name=..
134
131
  de->d_name=a1.txt
@@ -139,12 +136,12 @@
139
136
  directory: F:\teratail\teratail\aaa\bbb
140
137
  de->d_name=zzz
141
138
  directory: F:\teratail\teratail\aaa\zzz
142
- entry->path=F:\teratail\teratail\aaa\zzz
139
+ parent->path=F:\teratail\teratail\aaa\zzz
143
140
  de->d_name=.
144
141
  de->d_name=..
145
142
  de->d_name=z1.txt
146
143
  file: F:\teratail\teratail\aaa\zzz\z1.txt
147
- entry->path=F:\teratail\teratail\aaa\bbb
144
+ parent->path=F:\teratail\teratail\aaa\bbb
148
145
  de->d_name=.
149
146
  de->d_name=..
150
147
  de->d_name=b1.txt

2

コード修正

2022/11/01 08:35

投稿

jimbe
jimbe

スコア12696

test CHANGED
@@ -44,12 +44,13 @@
44
44
 
45
45
  void pushStack(Stack *stack, StackEntry *entry) {
46
46
  if(stack->top == stack->capa || stack->entries == NULL) {
47
- stack->capa += 10;
47
+ int capa = stack->capa + 10;
48
- StackEntry **p = realloc(stack->entries, sizeof(StackEntry *) * stack->capa);
48
+ StackEntry **p = realloc(stack->entries, sizeof(StackEntry *) * capa);
49
49
  if(p == NULL) {
50
50
  printf("pushStack: realloc error.");
51
51
  exit(1);
52
52
  }
53
+ stack->capa = capa;
53
54
  stack->entries = p;
54
55
  }
55
56
  stack->entries[stack->top++] = entry;
@@ -81,6 +82,11 @@
81
82
  }
82
83
 
83
84
  void printdir(char *path){
85
+ if(!isDirectory(path)) {
86
+ printf("file: %s\n", path);
87
+ return;
88
+ }
89
+
84
90
  Stack *stack = allocStack();
85
91
  pushStack(stack, allocEntry(path));
86
92
 

1

追加

2022/11/01 08:19

投稿

jimbe
jimbe

スコア12696

test CHANGED
@@ -1,2 +1,146 @@
1
1
  スタック内に保存するパスは全て違うのですから struct st 毎に領域が必要なのに、全て path になってしまっています。
2
2
  struct st のメンバ p は char ポインタではなく char 配列とし、 path の内容をコピーして保存することになるのでは無いでしょうか。(alloc してもいいですけど。)
3
+
4
+ ---
5
+ struct st の要素の使い方よりも、全体的に妙なことになっています。
6
+ st.l が dirent 配列としても st.i は必要無いはずです。(dopen とか dread がどういうモノなのかはっきりしませんが。)
7
+ スタックにはパスだけあれば十分だと思います。
8
+
9
+ ```c
10
+ #include <stdio.h>
11
+ #include <stdlib.h>
12
+ #include <string.h>
13
+ #include <dirent.h>
14
+ #include <sys/stat.h>
15
+
16
+ typedef struct stat Stat;
17
+ typedef struct dirent DirEnt;
18
+
19
+ typedef struct {
20
+ char path[512];
21
+ } StackEntry;
22
+
23
+ typedef struct {
24
+ int top;
25
+ int capa;
26
+ StackEntry **entries;
27
+ } Stack;
28
+
29
+ Stack *allocStack() {
30
+ Stack *stack = malloc(sizeof(Stack));
31
+ memset(stack, 0, sizeof(Stack));
32
+ return stack;
33
+ }
34
+
35
+ void freeStack(Stack *stack) {
36
+ if(stack != NULL) {
37
+ if(stack->entries != NULL) {
38
+ for(int i=0; i<stack->top; i++) free(stack->entries[i]);
39
+ free(stack->entries);
40
+ }
41
+ free(stack);
42
+ }
43
+ }
44
+
45
+ void pushStack(Stack *stack, StackEntry *entry) {
46
+ if(stack->top == stack->capa || stack->entries == NULL) {
47
+ stack->capa += 10;
48
+ StackEntry **p = realloc(stack->entries, sizeof(StackEntry *) * stack->capa);
49
+ if(p == NULL) {
50
+ printf("pushStack: realloc error.");
51
+ exit(1);
52
+ }
53
+ stack->entries = p;
54
+ }
55
+ stack->entries[stack->top++] = entry;
56
+ }
57
+
58
+ StackEntry *popStack(Stack *stack) {
59
+ if(stack == NULL || stack->top == 0) return NULL;
60
+ return stack->entries[--stack->top];
61
+ }
62
+
63
+ StackEntry *allocEntry(char *path) {
64
+ StackEntry *entry = malloc(sizeof(StackEntry));
65
+ if(entry == NULL) {
66
+ printf("createEntry: malloc error.");
67
+ exit(1);
68
+ }
69
+ strcpy(entry->path, path);
70
+ return entry;
71
+ }
72
+
73
+ void freeEntry(StackEntry *entry) {
74
+ if(entry != NULL) free(entry);
75
+ }
76
+
77
+ int isDirectory(char *path) {
78
+ Stat st;
79
+ if(stat(path, &st)) return 0; //false
80
+ return (st.st_mode & S_IFMT) == S_IFDIR;
81
+ }
82
+
83
+ void printdir(char *path){
84
+ Stack *stack = allocStack();
85
+ pushStack(stack, allocEntry(path));
86
+
87
+ char work[1024];
88
+ for(StackEntry *entry; (entry=popStack(stack)) != NULL; ) {
89
+ printf("entry->path=%s\n", entry->path);
90
+ DIR *dir = opendir(entry->path);
91
+
92
+ for(DirEnt *de; (de=readdir(dir)) != NULL; ) {
93
+ printf("de->d_name=%s\n", de->d_name);
94
+ if(de->d_name[0] == '.') continue; //"."(カレント),".."(親)および'.'で始まる隠しファイルは無視
95
+
96
+ sprintf(work, "%s\\%s", entry->path, de->d_name);
97
+ if(isDirectory(work)) {
98
+ printf("directory: %s\n", work);
99
+ pushStack(stack, allocEntry(work));
100
+ } else {
101
+ printf("file: %s\n", work);
102
+ }
103
+ }
104
+ closedir(dir);
105
+ freeEntry(entry);
106
+ }
107
+
108
+ freeStack(stack);
109
+ }
110
+
111
+ int main(int argc, char *argv[]) {
112
+ if(argc != 2) {
113
+ fprintf(stderr, "Usage: %s <directory-path>\n", argv[0]);
114
+ exit(1);
115
+ }
116
+ printdir(argv[1]);
117
+ }
118
+ ```
119
+ フォルダ構成
120
+ ![フォルダのツリーの画像](https://ddjkaamml8q8x.cloudfront.net/questions/2022-11-01/a0ed1954-7a48-4fd3-a478-d0122da6db0c.png)
121
+
122
+ 実行結果
123
+ ```plain
124
+ > printdir F:\teratail\teratail\aaa
125
+ entry->path=F:\teratail\teratail\aaa
126
+ de->d_name=.
127
+ de->d_name=..
128
+ de->d_name=a1.txt
129
+ file: F:\teratail\teratail\aaa\a1.txt
130
+ de->d_name=a2.txt
131
+ file: F:\teratail\teratail\aaa\a2.txt
132
+ de->d_name=bbb
133
+ directory: F:\teratail\teratail\aaa\bbb
134
+ de->d_name=zzz
135
+ directory: F:\teratail\teratail\aaa\zzz
136
+ entry->path=F:\teratail\teratail\aaa\zzz
137
+ de->d_name=.
138
+ de->d_name=..
139
+ de->d_name=z1.txt
140
+ file: F:\teratail\teratail\aaa\zzz\z1.txt
141
+ entry->path=F:\teratail\teratail\aaa\bbb
142
+ de->d_name=.
143
+ de->d_name=..
144
+ de->d_name=b1.txt
145
+ file: F:\teratail\teratail\aaa\bbb\b1.txt
146
+ ```