最近做一个工具时,需要一个文件遍历算法,网上寻觅无果后,自己动手写了一个,本算法用了一个单向链表用来实现同级目录移动,用一个双向链表用来实现父子目录的下行和递归,摒弃了递归函数,因此不限制目录层数和子目录数量,适用所有的目录情况,所以拿出来分享一下,经反复测试,无内存泄露,需要的人就可以直接拿过去用了:
#include <windows.h>
typedef struct dirs //目录单元结构
{
char *file; //目录名
struct dirs *father; //父目录指针
struct dirs *child;//子目录指针
struct dirs *next;//下一个同级目录指针
} dirs_t;
void DelTree(dirs_t *peer) //销毁目录树函数
{
dirs_t *p=peer;
dirs_t *tmp;
while(p->father!=NULL||p->child!=NULL)
{
if(p->child!=NULL)
{
p=p->child;
p->father->child=p->next;
// continue;
}
else if(p->child==NULL&&p->father!=NULL)
{
tmp=p;
if(p->next!=NULL)
{
p=p->next;
p->father=p->next;
}
else
{
p=p->father;
p->child=NULL;
}
free(tmp->file);
free(tmp);
}
}
free(p);
}
int DirList(char *topdir) //功能函数
{
dirs_t *top,*p,*pfather,*tmp;
WIN32_FIND_DATA FindFileData;
HANDLE hFind = INVALID_HANDLE_VALUE;
int firstflag; //下行标志
char *pathname;
int pathsize;
char *ptmp;
int num=0;
top=(dirs_t *)malloc(sizeof(dirs_t));
if(top==NULL)
return -1;
top->file=topdir;
top->father=NULL;
top->next=NULL;
top->child=top;
p=top;
do
{
firstflag=0;
if(p->father!=NULL&&p->child==NULL)//上行判断
{
if(p->next!=NULL)
{
tmp=p;
p=p->next;
p->father->child=p->next;
free(tmp->file);
free(tmp);
}
else
{
tmp=p;
p=p->father;
p->child=NULL;
free(tmp->file);
free(tmp);
continue;
}
}
tmp=p;
pathsize=strlen(top->file);
while(tmp!=top)
{
pathsize+=strlen(tmp->file);
pathsize++;
tmp=tmp->father;
}
pathname=(char *)malloc((pathsize+6)*sizeof(char));
if(pathname==NULL)
{
DelTree(p);
return -1;
}
tmp=p;
strcpy(pathname,top->file);
ptmp=pathname+pathsize;
while(tmp!=top)
{
ptmp=ptmp-strlen(tmp->file);
memcpy(ptmp,tmp->file,strlen(tmp->file));
memcpy(ptmp-1,"\\",1);
ptmp--;
tmp=tmp->father;
}
pathname[pathsize]='\0';
strcat(pathname,"\\*.*");
hFind = FindFirstFile(pathname, &FindFileData);
if(hFind!=INVALID_HANDLE_VALUE)
{
if(strcmp(FindFileData.cFileName,".")!=0&&strcmp(FindFileData.cFileName,"..")!=0)
{
if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
p->child=(dirs_t *)malloc(sizeof(dirs_t));
if(p->child==NULL)
{
DelTree(p);
FindClose(hFind);
free(pathname);
return -1;
}
pfather=p;
p=p->child;
p->next=NULL;
p->child=p;
p->father=pfather;
firstflag=1;
p->file=(char *)malloc((strlen(FindFileData.cFileName)+1)*sizeof(char));
if(p->file==NULL)
{
DelTree(p);
FindClose(hFind);
free(pathname);
return -1;
}
strcpy(p->file,FindFileData.cFileName);
}
else
{
printf("%s\n",FindFileData.cFileName);
num++;
}
}
while(FindNextFile(hFind, &FindFileData))
{
if(strcmp(FindFileData.cFileName,".")!=0&&strcmp(FindFileData.cFileName,"..")!=0)
{
if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if(!firstflag) //下行标志
{
p->child=(dirs_t *)malloc(sizeof(dirs_t));
if(p->child==NULL)
{
DelTree(p);
FindClose(hFind);
free(pathname);
return -1;
}
pfather=p;
p=p->child;
p->father=pfather;
firstflag=1;
}
else
{
p->next=(dirs_t *)malloc(sizeof(dirs_t));
if(p->next==NULL)
{
DelTree(p);
FindClose(hFind);
free(pathname);
return -1;
}
p=p->next;
}
p->father=pfather;
p->next=NULL;
p->child=p;
p->file=(char *)malloc((strlen(FindFileData.cFileName)+1)*sizeof(char));
if(p->file==NULL)
{
DelTree(p);
FindClose(hFind);
free(pathname);
return -1;
}
strcpy(p->file,FindFileData.cFileName);
}
else
{
printf("%s\n",FindFileData.cFileName);
num++;
}
}
}
}
FindClose(hFind);
free(pathname);
if(firstflag!=0) //进入子目录
{
// updownflag=0;
p=p->father->child;
p->father->child=p->next;
}
else if(firstflag==0&&p->father!=NULL)
{
tmp=p;
if(p->next==NULL) //进入父目录
{
p=p->father;
p->child=NULL;
}
else //进入同级目录
{
p=p->next;
p->father->child=p->next;
}
free(tmp->file);
free(tmp);
}
else
{
break;
}
}
while(p->father!=NULL||p->child!=NULL);
free(top);
printf("共%d个文件\n",num);
return 0;
}