2015-07-12 82 views
0

所以main()应该提取我当前目录中的所有文件名,并将它们放入数组,然后检查文件是否为常规文件。然后,它将所有常规文件传递到fun()fopen()修改字符数组的奇怪错误? [C语言]

的问题是,即使main()传入一个有效的数组,(不是全部)阵列的一些元素被通过成为fun()

//Output of command line before array is passed into fun() 
reg 0: a.out 
reg 1: myar 
reg 2: proj2.tex 
reg 3: myar.c 
reg 4: ar 
reg 5: makefile 
reg 6: new.c 
reg 7: newfile.txt 
reg 8: newar 

//Output of command line after passed into fun() 
reg 0: 
reg 1: 
reg 2: 
reg 3: myar.c 
reg 4: 
reg 5: 
reg 6: 
reg 7: newfile.txt 
reg 8: newar 

后,非常奇怪的是,删除,如果我删除fun()中的fopen()声明,则没有任何问题。难道是fopen()正在修改它不应该是的东西吗?代码提供如下:

1 #include <stdio.h> 
    2 #include <stdlib.h> 
    3 #include <dirent.h> 
    4 #include <sys/stat.h> 
    5 
    6 void fun(char* arfile, char** filenames, int file_count) 
    7 { 
    8  int i; 
    9  FILE* f = fopen("text.txt", "a"); 
10 
11  for (i=0;i<file_count;i++){ 
12   printf("reg %d: %s\n",i,filenames[i]); 
13   fflush(stdout); 
14  } 
15 
16  fclose(f); 
17 } 
18 
19 
20 int main (int argc, char** argv) 
21 { 
22  struct stat s; 
23  DIR *d; 
24  struct dirent *dir; 
25  int i, file_count = 0, reg_count = 0; 
26  char **filenames, **regular_files; 
27  char *arfile; 
28 
29  if (argc != 2) 
30   exit(EXIT_FAILURE); 
31  else 
32   arfile = argv[1]; 
33 
34  d = opendir("."); 
35 
36  while ((dir = readdir(d)) != NULL){ 
37   file_count++; 
38  } 
39 
40  closedir(d); 
41  filenames  = malloc(file_count*sizeof(char*)); 
42  regular_files = malloc(file_count*sizeof(char*)); 
43 
44  d = opendir("."); 
45 
46  for (i = 0; (dir = readdir(d)) != NULL; i++){ 
47   filenames[i] = dir->d_name; 
48  } 
49 
50  closedir(d); 
51 
52  for (i = 2; i < file_count ; i++){ 
53   if (stat(filenames[i], &s) == -1) { 
54    perror("Unable to read file stats"); 
55    exit(EXIT_FAILURE); 
56   } 
57 
58   if (S_ISREG(s.st_mode)){ 
59    regular_files[reg_count] = filenames[i]; 
60    reg_count++; 
61   } 

62  } 
63 
64  for (i=0;i<reg_count;i++){ 
65   printf("reg %d: %s\n",i,regular_files[i]); 
66   fflush(stdout); 
67  } 
68  fun(arfile, regular_files, reg_count); 
69 
70  free(filenames); 
71  free(regular_files); 
72  return 0; 
73 } 
74 
+1

进一步调用'readdir()'后,不能挂在'dir-> d_name'上,当然不能在'closedir()'后面。你必须用'strdup()'或其他东西来复制它。 –

+0

这一行:'filenames [i] = dir-> d_name;'有两个问题:1)这不会复制名称,只有dir-> d_name的地址。建议strcpy(文件名[i],dir-> d_name);' 2)malloc()只分配了一个指向char的指针数组。每个文件名[i]实际上都没有特别指出。 (应该将它们初始化为全空以使调用free()简单)建议:filenames [i] = malloc(strlen(dir-> d_name)+1);当然,每次调用malloc之后都需要检查(!= NULL)以确保操作成功。 – user3629249

+0

关于此行:'exit(EXIT_FAILURE);'仅仅因为一个文件不能'stat'ed,并不意味着其他文件不能'stat'ed。建议围绕这个问题的逻辑工作,而不是突然退出程序。强烈建议阅读关于'stat' – user3629249

回答

1

readdir是非重入功能 - 它持有临时静态缓冲区这是在每次迭代之后覆盖,所以通过dir->d_name称为数据变为无效。你需要与strdup()复制它们,即:

for (i = 0; (dir = readdir(d)) != NULL; i++) {  
    filenames[i] = strdup(dir->d_name); 
} 

而且不要忘记释放分配的字符串:

for (i = 0; i < file_count; i++) {  
    free(filenames[i]); 
} 

你也可以看重入的功能,如readdir_r,但他们并没有太大的帮助的在你的情况。

+0

哦,这是有道理的!非常感谢你,你还救了我两个小时 – loukouk