2015-07-12 81 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