用"树"存储目录结构输出时出现了乱码


问题1: 存储某个文件目录结构时应用什么数据结构更为恰当?

问题2: 我的想法是用一般"树"结构来存储,但是有很多问题:

1.某个目录下的文件数可能不一样,这样每个树结点(只有目录才有子结点,叶结点为文件(或空 目录))的子结点数就不是确定的,这样可以在每个树结点中添加一个关键字 nchild 来表明其有 nchild 个子结点(即有 n 个指向子结点的指针 *child ,下面的程序采用 **child 来存储这 些指针).

2.这样一来就要动态地为 **child 的指向分配空间,可是这样一做后面就太不好释放(下面的程序压根就没有释放)? 这怎么办?

3.还有就是运行下面的程序有时会输出乱码的文件路径名,这是怎么回事?调试的时候发现是 ent=readdir(pDir) 读出了一个乱码的 ent->d_name .但是单独写一个程序读同一个目录又没这种问题.我觉得可能递归调用出现了问题,但还是找不出问题的原因?希望大家花点时间帮忙看看,在这里谢过了.


 #include <stdio.h>
#include <dirent.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>

typedef struct tree_file_s
{
  char path[512];
  time_t date;
  char type;
  long size;
  int nchild;

  struct tree_file_s **child;
} tree_file_t;

int dir_child_len(const char *dir)
{
  int nchild = 0;
  DIR *pDir;
  struct dirent *ent;

  pDir = opendir(dir);
  while((ent=readdir(pDir)) != NULL)
  {
    if (strcmp(ent->d_name, ".")==0 || strcmp(ent->d_name, "..")==0) 
    {
      continue; 
    }
    nchild++;
  }

  return nchild;
}

void tree_create(tree_file_t *tft, const char *dir)
{
  int nchild; // the tft has n child
  DIR *pDir;
  struct dirent *ent; // the directory dir dirent info
  struct stat file_stat; // the new file's stat info

  stat(dir, &file_stat);
  nchild = dir_child_len(dir);
  pDir = opendir(dir);

  // Initialize the parent
  //tft->path = calloc(1, strlen(dir)+1);
  strcpy(tft->path, dir);
  tft->date = file_stat.st_mtime;
  tft->type = 'D';
  tft->size = file_stat.st_size;
  tft->nchild = nchild;
  tft->child = calloc(1, nchild);

  nchild = 0;
   while ((ent=readdir(pDir)) != NULL) 
   {
      if (ent->d_type & DT_DIR) 
      {
         if (strcmp(ent->d_name, ".")==0 || strcmp(ent->d_name, "..")==0) 
         {
           continue; 
         }
         tree_file_t *new_dir = calloc(1, sizeof(tree_file_t));
         tft->child[nchild] = new_dir;

         char *new_path = calloc(1, strlen(dir)+strlen(ent->d_name)+1);
         sprintf(new_path, "%s/%s", dir, ent->d_name);
         tree_create(new_dir, new_path);
         free(new_path);
      } else {
        tree_file_t *new_file = calloc(1, sizeof(tree_file_t));
        char *new_path = calloc(1, strlen(dir)+strlen(ent->d_name)+1);
        // new_file->path = calloc(1, strlen(dir)+strlen(ent->d_name)+1);
        sprintf(new_path, "%s/%s", dir, ent->d_name);
        stat(new_path, &file_stat);
        strcpy(new_file->path, new_path);
        free(new_path);
        new_file->date = file_stat.st_mtime;
        new_file->type = 'F';
        new_file->size = file_stat.st_size;
        new_file->nchild = 0;
        new_file->child = 0;

        tft->child[nchild] = new_file;
      }
      //free(new_path);
      //new_path = 0;
      nchild++;
   }
}

void display_tree(tree_file_t *tft)
{
  int nchild, i;

  nchild = tft->nchild;

  printf("%c: %s\n", tft->type, tft->path);

  for(i = 0; i < nchild; i++)
  {
    if(tft->child[i]->type == 'F')
    {
      printf("%c: %s\n",  tft->child[i]->type, tft->child[i]->path);
    } else {
      display_tree(tft->child[i]);
    }
  }
}

int main(int argc, const char *argv[])
{
  if(argc != 2)
  {
    printf("Usage: a.out dir\n");
    exit(0);
  }

  char dir[512];
  strcpy(dir, argv[1]);
  tree_file_t *tft = calloc(1, sizeof(tree_file_t));
  tree_create(tft, dir);
  display_tree(tft);

  return 0;
}

c 编程 Linux unix

Oo凡星oO 11 years, 1 month ago

我看你对同一个dir打开了两次,会不会造成你说的乱码问题啊。
在dir_child_len里面给关掉试试。

相对1的⑥酱 answered 11 years, 1 month ago

Your Answer