《C语言实现的获取某目录及其子目录下所有文件的绝对路径》
http://topic.csdn.net/u/20111223/00/d1148664-affb-49ce-bff1-d3bd107ffaf4.html
之前不知道使用链表,直接递归实现,结果测试的时候,程序总是会爆栈。
这些改进了,使用链表来实现,测试结果很满意。可以遍历整个磁盘。
链表的结构定义如下:
/* 定义结构体 */
typedef struct folder_node_tag
{
char *name_ptr; //自己的名字
int name_leng; //名字的长度
int is_visited; //是否已经被访问了
struct folder_node_tag *parent_ptr; //其父
struct folder_node_tag *prev_brother_ptr; //其兄
struct folder_node_tag *next_brother_ptr; //其弟
struct folder_node_tag *first_child_ptr; //长子
}FOLDER_NODE_T;
/* 搜索时下一步的定义 */
typedef enum next_find_action_e
{
NFA_IS_ENTRY_SUBDIR, // 下一步是进入子目录
NFA_IS_ENTRY_PARENT, // 下一步是返回上级目录
NFA_IS_TERMINATE_CURR, // 终止本次搜索
NFA_IS_EXIT_SEARCH, // 下一步是终止所有搜索
NFA_IS_UNDEFINED, // 未定义,什么也不做
}NEXT_FIND_ACTION_E;
好了,还有一些其他的代码,以后慢慢贴。
15 个解决方案
#1
/* 搜索某个目录,在搜索完这一层目录后就直接返回了,不主动进入下级目录 */
static NEXT_FIND_ACTION_E ts_search_in_node(FOLDER_NODE_T *rootp, FOLDER_NODE_T **retnode)
{
FOLDER_NODE_T *new_node = NULL;
FOLDER_NODE_T *old_node = NULL;
FINDDATA_T finddata = {0};
FINDDATA_HANDLE fileHandle = INVALID_HANDLE;
NEXT_FIND_ACTION_E next_do = NFA_IS_ENTRY_PARENT;
char *tobefind = NULL;
int cwlength = 0;
char cwpath[MAX_PATH+4]={0}; // "cd path"
if(TS_GETCWD(cwpath, MAX_PATH))
{
MSG_SHOW("ts_search_in_node at: %s.\n",cwpath);
}
else
{
MSG_SHOW("ts_search_in_node get current work directory failed!\n");
next_do = NFA_IS_TERMINATE_CURR;
goto exit_tag;
}
// 先赋值,让返回去的node为空,以便后面程序的判断
*retnode = NULL;
// 是否需要chdir这个函数来修改工作时的路径呢
if(rootp == NULL)
{
MSG_SHOW("Passed a NULL pointer (rootp)! Terminate current search!\n");
next_do = NFA_IS_TERMINATE_CURR;
goto exit_tag;
}
if(retnode == NULL)
{
MSG_SHOW("Passed a NULL pointer (retnode)! Terminate current search!\n");
next_do = NFA_IS_TERMINATE_CURR;
goto exit_tag;
}
cwlength = TS_STRLEN(cwpath);
// tobefind --> D:\testfolder\*.*
#if defined(MEM_LEAK_CHECK)
tobefind = (char*)ts_alloc_with_mem_check(cwlength+1+4);
#else
tobefind = (char*)TS_MALLOC(cwlength+1+4);
#endif
if(tobefind == NULL)
{
MSG_SHOW("Can not allocate memory for variable!\n");
next_do = NFA_IS_TERMINATE_CURR;
goto exit_tag;
}
TS_MEMSET(tobefind, 0, cwlength+1+4);
TS_STRCPY(tobefind, cwpath);
TS_STRCPY(tobefind+cwlength, "\\*.*");
MSG_SHOW("find in [%s]\n", tobefind);
fileHandle = _findfirst(tobefind, &finddata);
new_node = old_node = NULL;
if(fileHandle == INVALID_HANDLE)
{
MSG_SHOW("Find first return invalid handle!\n");
next_do = NFA_IS_TERMINATE_CURR;
}
else
{
do
{
if ((finddata.attrib & _A_SUBDIR) && (finddata.name[0] != '.'))
{
//DBG_PRINT("Find a folder \"%s\".\n", finddata.name);
RECORD_TO(FOLDER_LIST, "%s\\%s\n", cwpath, finddata.name);
new_node = ts_alloc_node(finddata.name, TS_STRLEN(finddata.name));
if (new_node == NULL)
{
MSG_SHOW("Find a folder but can not allocate memory!\n");
next_do = NFA_IS_EXIT_SEARCH;
break;
}
else if (old_node == NULL)
{
// 认为是第一个孩子,
rootp->first_child_ptr = new_node;
new_node->parent_ptr = rootp;
}
else
{
old_node->next_brother_ptr = new_node;
new_node->prev_brother_ptr = old_node;
}
old_node = new_node;
// 有找到文件夹,则需要继续深入,不返回上一级目录
// 准备进入最后一个找到的文件夹
next_do = NFA_IS_ENTRY_SUBDIR;
*retnode = new_node;
searched_folder_total ++;
}
else if ((finddata.attrib & _A_SUBDIR) && (finddata.name[0] == '.'))
{
/* "." 和 ".." 而且 ".svn" 这样的特殊文件夹也会被忽略 */
}
else
{
//DBG_PRINT("Find a file \"%s\".\n", finddata.name);
RECORD_TO(FILE_LIST, "%s\\%s\n", cwpath, finddata.name);
/* do something you want to ... */
searched_file_total ++;
}
}while(_findnext(fileHandle, &finddata) != INVALID_HANDLE);
//关闭当前正在查找的文件夹的句柄
_findclose(fileHandle);
}
exit_tag:
if(tobefind != NULL)
{
#if defined(MEM_LEAK_CHECK)
ts_free_with_mem_check((void*)tobefind);
#else
TS_FREE(tobefind);
#endif
tobefind = NULL;
}
return next_do;
}
#2
/* 启动搜索 */
static PROG_RET_VAL_E ts_do_search(FOLDER_NODE_T **rootp)
{
int loop_next = TRUE;
int find_upper = TRUE;
int cwpath_ret_level = 0;
int cwlength = 0;
int func_ret_val = 0;
char cwpath[MAX_PATH] = {0}; // "cd path"
FOLDER_NODE_T *sub_root = *rootp;
FOLDER_NODE_T *ret_root = NULL;
FOLDER_NODE_T *to_be_del = NULL;
PROG_RET_VAL_E ret_val = PROG_RET_SUCESSFUL;
NEXT_FIND_ACTION_E action = NFA_IS_ENTRY_SUBDIR;
//切换工作路径,后面就利用系统的cd命令根据action来决定是进入还是退出
if(rootp == NULL || *rootp == NULL)
{
MSG_SHOW("Parameter passed to ts_do_search is NULL!\n");
ret_val = PROG_RET_ILLEGAL_PARA;
goto exit_func;
}
if (sub_root->name_leng > 3
&& sub_root->name_ptr[1] == ':'
&& (sub_root->name_ptr[2] == '\\' || sub_root->name_ptr[2] == '/'))
{
func_ret_val = TS_CHDIR(sub_root->name_ptr);
if(func_ret_val != 0)
{
MSG_SHOW("Change directory filed or directory is not exist! func_ret_val=%d.\n",func_ret_val);
ret_val = PROG_RET_PATH_NOT_EXIST;
goto exit_func;
}
}
if(TS_GETCWD(cwpath, MAX_PATH))
{
MSG_SHOW("ts_do_search at: %s.\n",cwpath);
}
else
{
MSG_SHOW("ts_do_search get current work directory failed!\n");
ret_val = PROG_RET_GET_WD_FAIL;
goto exit_func;
}
// 移除路径末尾的路径分隔符
if(cwpath[cwlength - 1] == '\\' || cwpath[cwlength - 1] == '/')
{
cwpath[cwlength - 1] = '\0';
cwlength -= 1;
}
if(FILE_LIST == NULL)
{
MSG_SHOW("Create searched_file.lst at %s.\n",cwpath);
FILE_LIST = fopen("searched_file.lst", "wb");
}
if(FOLDER_LIST == NULL)
{
MSG_SHOW("Create searched_folder.lst at %s.\n",cwpath);
FOLDER_LIST = fopen("searched_folder.lst", "wb");
}
do
{
to_be_del = sub_root;
action = ts_search_in_node(sub_root, &ret_root);
switch(action)
{
case NFA_IS_ENTRY_SUBDIR:
DBG_PRINT("==>NFA_IS_ENTRY_SUBDIR\n");
if(ret_root != NULL)
{
sub_root = ret_root;
//要修正下路径,否则查找会失败的
ts_path_combine(cwpath, TS_STRLEN(cwpath), sub_root->name_ptr, sub_root->name_leng, MAX_PATH);
TS_CHDIR(cwpath);
ret_root = NULL;
}
else
{
MSG_SHOW("There must be some error!\n");
loop_next = FALSE;
}
break;
case NFA_IS_ENTRY_PARENT:
DBG_PRINT("==>NFA_IS_ENTRY_PARENT\n");
cwpath_ret_level = 0;
do
{
find_upper = FALSE;
cwpath_ret_level += 1;
if(sub_root == NULL)
{
loop_next = FALSE;
}
else if (sub_root->prev_brother_ptr != NULL)
{
to_be_del = sub_root;
sub_root = sub_root->prev_brother_ptr;
}
else
{
if(sub_root->parent_ptr != NULL)
{
DBG_PRINT("find_upper: sub_root->parent = %s.\n", sub_root->parent_ptr->name_ptr);
}
to_be_del = sub_root;
sub_root = sub_root->parent_ptr;
find_upper = TRUE;
}
}while(find_upper);
/* 如果到了*节点,注意删除后将指针设置成空 */
if(to_be_del == *rootp)
{
ts_delete_node(&to_be_del);
//注意将指针设置成NULL
*rootp = NULL;
}
else
{
ts_delete_node(&to_be_del);
}
if(loop_next)
{
//要修正下路径,否则查找会失败的
ts_path_back(cwpath, TS_STRLEN(cwpath), cwpath_ret_level);
ts_path_combine(cwpath, TS_STRLEN(cwpath), sub_root->name_ptr, sub_root->name_leng, MAX_PATH);
TS_CHDIR(cwpath);
}
break;
case NFA_IS_TERMINATE_CURR:
// 这个case下面的还没调试过,暂时采用NFA_IS_ENTRY_PARENT同样的处理
DBG_PRINT("==>NFA_IS_TERMINATE_CURR\n");
cwpath_ret_level = 0;
do
{
find_upper = FALSE;
cwpath_ret_level += 1;
if(sub_root == NULL)
{
loop_next = FALSE;
}
else if (sub_root->prev_brother_ptr != NULL)
{
to_be_del = sub_root;
sub_root = sub_root->prev_brother_ptr;
}
else
{
if(sub_root->parent_ptr != NULL)
{
DBG_PRINT("find_upper: sub_root->parent = %s.\n", sub_root->parent_ptr->name_ptr);
}
to_be_del = sub_root;
sub_root = sub_root->parent_ptr;
find_upper = TRUE;
}
}while(find_upper);
/* 如果到了*节点,注意删除后将指针设置成空 */
if(to_be_del == *rootp)
{
ts_delete_node(&to_be_del);
//注意将指针设置成NULL
*rootp = NULL;
}
else
{
ts_delete_node(&to_be_del);
}
if(loop_next)
{
//要修正下路径,否则查找会失败的
ts_path_back(cwpath, TS_STRLEN(cwpath), cwpath_ret_level);
ts_path_combine(cwpath, TS_STRLEN(cwpath), sub_root->name_ptr, sub_root->name_leng, MAX_PATH);
TS_CHDIR(cwpath);
}
break;
case NFA_IS_EXIT_SEARCH:
MSG_SHOW("The last search returned NFA_IS_EXIT_SEARCH, stop all search!\n");
ts_delete_node(rootp);
//注意将指针设置成NULL
to_be_del = NULL;
*rootp = NULL;
ret_val = PROG_RET_PROG_TERMINATE;
loop_next = FALSE;
break;
default:
MSG_SHOW("The last search returned a unknown error, stop all search!\n");
ts_delete_node(rootp);
//注意将指针设置成NULL
to_be_del = NULL;
*rootp = NULL;
ret_val = PROG_RET_UNKNOWN_ERR;
loop_next = FALSE;
break;
}
} while (loop_next);
exit_func:
return ret_val;
}
#3
其中,为了检测内存泄露,特地使用一个函数,改装内存的申请与释放过程,代码如下:
#if defined(MEM_LEAK_CHECK)
static long int memoryUsedMax = 0;
static long int memoryUsedCur = 0;
static MEM_LEAK_T *memLeakListPtr = NULL;
static void* ts_alloc_with_mem_check(size_t memsize)
{
void *allocated_mem_ptr = NULL;
register MEM_LEAK_T *newnode = NULL;
register MEM_LEAK_T *prevnode = NULL;
register MEM_LEAK_T *currnode = memLeakListPtr;
allocated_mem_ptr = (void*)TS_MALLOC(memsize);
if(allocated_mem_ptr != NULL)
{
newnode = (MEM_LEAK_T*)TS_MALLOC(sizeof(MEM_LEAK_T));
if(newnode != NULL)
{
/* 申请一个新的节点,记录内存申请信息,插入链表 */
newnode->memAdr = (int)allocated_mem_ptr;
newnode->memSize = memsize;
newnode->next = NULL;
while(currnode != NULL)
{
prevnode = currnode;
currnode = currnode->next;
}
if(prevnode == NULL)
{
memLeakListPtr = newnode;
}
else
{
prevnode->next = newnode;
}
memoryUsedCur += (memsize + sizeof(MEM_LEAK_T));
if(memoryUsedMax<memoryUsedCur)
{
memoryUsedMax = memoryUsedCur;
}
}
}
else
{
MEM_PRINT("ts_alloc_with_mem_check FAILED!\n");
}
return allocated_mem_ptr;
}
static void ts_free_with_mem_check(void* memPtr)
{
register MEM_LEAK_T *currnode = memLeakListPtr;
register MEM_LEAK_T *prevnode = NULL;
while(currnode != NULL)
{
if(currnode->memAdr == (int)memPtr)
{
break;
}
else
{
prevnode = currnode;
currnode = currnode->next;
}
}
TS_FREE(memPtr);
if(currnode != NULL)
{
memoryUsedCur -= (currnode->memSize + sizeof(MEM_LEAK_T));
if(prevnode != NULL)
{
prevnode->next = currnode->next;
currnode->next = NULL;
TS_FREE(currnode);
currnode = NULL;
}
else
{
/* the head of list */
if(currnode->next == NULL)
{
TS_FREE(currnode);
currnode = NULL;
memLeakListPtr = NULL;
}
else
{
memLeakListPtr = currnode->next;
currnode->next = NULL;
TS_FREE(currnode);
currnode = NULL;
}
}
}
}
static void ts_mem_check_at_prog_exit(void)
{
int no_memory_leak_flag = TRUE;
register MEM_LEAK_T *currnode = memLeakListPtr;
register MEM_LEAK_T *prevnode = NULL;
while(currnode != NULL)
{
MEM_PRINT("\nmemory leaked at 0x%08x, size is %4d bytes.", currnode->memAdr, currnode->memSize);
prevnode = currnode;
currnode = currnode->next;
TS_FREE((void*)(prevnode->memAdr));
TS_FREE(prevnode);
no_memory_leak_flag = FALSE;
}
if(no_memory_leak_flag)
{
MEM_PRINT("There is no memory leak. memoryUsedCur=%d.\n",memoryUsedCur);
MSG_SHOW("memoryUsedMax=%d.\n",memoryUsedMax);
}
}
#endif /*defined(MEM_LEAK_CHECK)*/
#4
不错 如果是我我会选择用树来实现
#5
请问,如果用树来实现的话,其基本思路是怎样的呢?
我没学过数据结构,很多东西都不太理解。希望你能稍微做点提醒,得空我再研究下树的实现。
#6
刚才去百度了下,你说的树,指的是二叉树吧?深度优先搜索和广度优先搜索,是不?这两个算法的概念我看了下,但是没有确切的实践,始终没法理解透彻,也没法实际应用。不知道你能否开个贴,示意部分代码,参考学习下呢?
#7
[liangdong@bb-browser-test00.vm.baidu.com c_project]$ make
gcc -g -I. -I../libs/include -c -o main.o main.c
gcc -o main main.o
[liangdong@bb-browser-test00.vm.baidu.com c_project]$ ./main
/home/liangdong/c_project/main.c
楼主辛苦了。
#8
NAME
glob, globfree - find pathnames matching a pattern, free memory from glob()
SYNOPSIS
#include <glob.h>
int glob(const char *pattern, int flags,
int errfunc(const char *epath, int eerrno),
glob_t *pglob);
void globfree(glob_t *pglob);
NAME
realpath - return the canonicalized absolute pathname
SYNOPSIS
#include <limits.h>
#include <stdlib.h>
char *realpath(const char *path, char *resolved_path);
#9
[liangdong@bb-browser-test00.vm.baidu.com c_project]$ cat main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
int main(int argc, char* const argv[]) {
char path[PATH_MAX];
if (realpath("./main.c", path) != NULL) {
printf("%s\n", path);
}
return 0;
}
忘了贴代码。
#10
你用代码描述了这么多,好像,没有说明什么,我去百度了一下,你调用的这个函数好像是用来获取文件的绝对路径的。
realpath()用来将参数path所指的相对路径转换成绝对路径后存于参数resolved_path所指的字符串数组或指针中 返回值: 成功则返回指向resolved_path的指针,失败返回NULL,错误代码存于errno
这似乎跟遍历文件夹的联系不大啊。
#11
还是觉得递归比较好用。
#12
system("dir /b /s /a-d c:\\*.* >d:\\allfiles.txt");
//读文件d:\\allfiles.txt的内容即C:\\下所有文件的绝对路径
请记住,能用shell命令获取文件、文件夹信息或者操作文件、文件夹最好用shell命令获取或者操作,而不要用各种API获取或者操作,因为当遇到非法文件夹名或非法文件名或非法文件长度、非法文件日期、压缩文件、链接文件、稀疏文件……等各种意料之外的情况时,API会处理的不全面或陷入死循环,而shell命令不会。
//读文件d:\\allfiles.txt的内容即C:\\下所有文件的绝对路径
请记住,能用shell命令获取文件、文件夹信息或者操作文件、文件夹最好用shell命令获取或者操作,而不要用各种API获取或者操作,因为当遇到非法文件夹名或非法文件名或非法文件长度、非法文件日期、压缩文件、链接文件、稀疏文件……等各种意料之外的情况时,API会处理的不全面或陷入死循环,而shell命令不会。
#13
大佬,又看到你来顶我的帖子了。我记得我以前提这个问题的时候你就是这么指导的。你说的很对。
我在编写这个程序的时候还在担心如果碰到unicode字符的文件名的时候,我的strlen, strcpy还有效么?
庆幸的是,我在VC6下测试,暂时没发现什么异常。想来是VC6里面的库支持unicode吧。
通过这个实践,我对之前学习C语言的链表的内容有了很大程度掌握。这个才是关键!
谢谢你的指导!
#14
试想如果你的文件夹深度在8纪以上,文件夹数量上万,文件的数量也上万,此时,来用用你的递归,是否存在局限呢?
#15
楼主,威武,代码………………
#1
/* 搜索某个目录,在搜索完这一层目录后就直接返回了,不主动进入下级目录 */
static NEXT_FIND_ACTION_E ts_search_in_node(FOLDER_NODE_T *rootp, FOLDER_NODE_T **retnode)
{
FOLDER_NODE_T *new_node = NULL;
FOLDER_NODE_T *old_node = NULL;
FINDDATA_T finddata = {0};
FINDDATA_HANDLE fileHandle = INVALID_HANDLE;
NEXT_FIND_ACTION_E next_do = NFA_IS_ENTRY_PARENT;
char *tobefind = NULL;
int cwlength = 0;
char cwpath[MAX_PATH+4]={0}; // "cd path"
if(TS_GETCWD(cwpath, MAX_PATH))
{
MSG_SHOW("ts_search_in_node at: %s.\n",cwpath);
}
else
{
MSG_SHOW("ts_search_in_node get current work directory failed!\n");
next_do = NFA_IS_TERMINATE_CURR;
goto exit_tag;
}
// 先赋值,让返回去的node为空,以便后面程序的判断
*retnode = NULL;
// 是否需要chdir这个函数来修改工作时的路径呢
if(rootp == NULL)
{
MSG_SHOW("Passed a NULL pointer (rootp)! Terminate current search!\n");
next_do = NFA_IS_TERMINATE_CURR;
goto exit_tag;
}
if(retnode == NULL)
{
MSG_SHOW("Passed a NULL pointer (retnode)! Terminate current search!\n");
next_do = NFA_IS_TERMINATE_CURR;
goto exit_tag;
}
cwlength = TS_STRLEN(cwpath);
// tobefind --> D:\testfolder\*.*
#if defined(MEM_LEAK_CHECK)
tobefind = (char*)ts_alloc_with_mem_check(cwlength+1+4);
#else
tobefind = (char*)TS_MALLOC(cwlength+1+4);
#endif
if(tobefind == NULL)
{
MSG_SHOW("Can not allocate memory for variable!\n");
next_do = NFA_IS_TERMINATE_CURR;
goto exit_tag;
}
TS_MEMSET(tobefind, 0, cwlength+1+4);
TS_STRCPY(tobefind, cwpath);
TS_STRCPY(tobefind+cwlength, "\\*.*");
MSG_SHOW("find in [%s]\n", tobefind);
fileHandle = _findfirst(tobefind, &finddata);
new_node = old_node = NULL;
if(fileHandle == INVALID_HANDLE)
{
MSG_SHOW("Find first return invalid handle!\n");
next_do = NFA_IS_TERMINATE_CURR;
}
else
{
do
{
if ((finddata.attrib & _A_SUBDIR) && (finddata.name[0] != '.'))
{
//DBG_PRINT("Find a folder \"%s\".\n", finddata.name);
RECORD_TO(FOLDER_LIST, "%s\\%s\n", cwpath, finddata.name);
new_node = ts_alloc_node(finddata.name, TS_STRLEN(finddata.name));
if (new_node == NULL)
{
MSG_SHOW("Find a folder but can not allocate memory!\n");
next_do = NFA_IS_EXIT_SEARCH;
break;
}
else if (old_node == NULL)
{
// 认为是第一个孩子,
rootp->first_child_ptr = new_node;
new_node->parent_ptr = rootp;
}
else
{
old_node->next_brother_ptr = new_node;
new_node->prev_brother_ptr = old_node;
}
old_node = new_node;
// 有找到文件夹,则需要继续深入,不返回上一级目录
// 准备进入最后一个找到的文件夹
next_do = NFA_IS_ENTRY_SUBDIR;
*retnode = new_node;
searched_folder_total ++;
}
else if ((finddata.attrib & _A_SUBDIR) && (finddata.name[0] == '.'))
{
/* "." 和 ".." 而且 ".svn" 这样的特殊文件夹也会被忽略 */
}
else
{
//DBG_PRINT("Find a file \"%s\".\n", finddata.name);
RECORD_TO(FILE_LIST, "%s\\%s\n", cwpath, finddata.name);
/* do something you want to ... */
searched_file_total ++;
}
}while(_findnext(fileHandle, &finddata) != INVALID_HANDLE);
//关闭当前正在查找的文件夹的句柄
_findclose(fileHandle);
}
exit_tag:
if(tobefind != NULL)
{
#if defined(MEM_LEAK_CHECK)
ts_free_with_mem_check((void*)tobefind);
#else
TS_FREE(tobefind);
#endif
tobefind = NULL;
}
return next_do;
}
#2
/* 启动搜索 */
static PROG_RET_VAL_E ts_do_search(FOLDER_NODE_T **rootp)
{
int loop_next = TRUE;
int find_upper = TRUE;
int cwpath_ret_level = 0;
int cwlength = 0;
int func_ret_val = 0;
char cwpath[MAX_PATH] = {0}; // "cd path"
FOLDER_NODE_T *sub_root = *rootp;
FOLDER_NODE_T *ret_root = NULL;
FOLDER_NODE_T *to_be_del = NULL;
PROG_RET_VAL_E ret_val = PROG_RET_SUCESSFUL;
NEXT_FIND_ACTION_E action = NFA_IS_ENTRY_SUBDIR;
//切换工作路径,后面就利用系统的cd命令根据action来决定是进入还是退出
if(rootp == NULL || *rootp == NULL)
{
MSG_SHOW("Parameter passed to ts_do_search is NULL!\n");
ret_val = PROG_RET_ILLEGAL_PARA;
goto exit_func;
}
if (sub_root->name_leng > 3
&& sub_root->name_ptr[1] == ':'
&& (sub_root->name_ptr[2] == '\\' || sub_root->name_ptr[2] == '/'))
{
func_ret_val = TS_CHDIR(sub_root->name_ptr);
if(func_ret_val != 0)
{
MSG_SHOW("Change directory filed or directory is not exist! func_ret_val=%d.\n",func_ret_val);
ret_val = PROG_RET_PATH_NOT_EXIST;
goto exit_func;
}
}
if(TS_GETCWD(cwpath, MAX_PATH))
{
MSG_SHOW("ts_do_search at: %s.\n",cwpath);
}
else
{
MSG_SHOW("ts_do_search get current work directory failed!\n");
ret_val = PROG_RET_GET_WD_FAIL;
goto exit_func;
}
// 移除路径末尾的路径分隔符
if(cwpath[cwlength - 1] == '\\' || cwpath[cwlength - 1] == '/')
{
cwpath[cwlength - 1] = '\0';
cwlength -= 1;
}
if(FILE_LIST == NULL)
{
MSG_SHOW("Create searched_file.lst at %s.\n",cwpath);
FILE_LIST = fopen("searched_file.lst", "wb");
}
if(FOLDER_LIST == NULL)
{
MSG_SHOW("Create searched_folder.lst at %s.\n",cwpath);
FOLDER_LIST = fopen("searched_folder.lst", "wb");
}
do
{
to_be_del = sub_root;
action = ts_search_in_node(sub_root, &ret_root);
switch(action)
{
case NFA_IS_ENTRY_SUBDIR:
DBG_PRINT("==>NFA_IS_ENTRY_SUBDIR\n");
if(ret_root != NULL)
{
sub_root = ret_root;
//要修正下路径,否则查找会失败的
ts_path_combine(cwpath, TS_STRLEN(cwpath), sub_root->name_ptr, sub_root->name_leng, MAX_PATH);
TS_CHDIR(cwpath);
ret_root = NULL;
}
else
{
MSG_SHOW("There must be some error!\n");
loop_next = FALSE;
}
break;
case NFA_IS_ENTRY_PARENT:
DBG_PRINT("==>NFA_IS_ENTRY_PARENT\n");
cwpath_ret_level = 0;
do
{
find_upper = FALSE;
cwpath_ret_level += 1;
if(sub_root == NULL)
{
loop_next = FALSE;
}
else if (sub_root->prev_brother_ptr != NULL)
{
to_be_del = sub_root;
sub_root = sub_root->prev_brother_ptr;
}
else
{
if(sub_root->parent_ptr != NULL)
{
DBG_PRINT("find_upper: sub_root->parent = %s.\n", sub_root->parent_ptr->name_ptr);
}
to_be_del = sub_root;
sub_root = sub_root->parent_ptr;
find_upper = TRUE;
}
}while(find_upper);
/* 如果到了*节点,注意删除后将指针设置成空 */
if(to_be_del == *rootp)
{
ts_delete_node(&to_be_del);
//注意将指针设置成NULL
*rootp = NULL;
}
else
{
ts_delete_node(&to_be_del);
}
if(loop_next)
{
//要修正下路径,否则查找会失败的
ts_path_back(cwpath, TS_STRLEN(cwpath), cwpath_ret_level);
ts_path_combine(cwpath, TS_STRLEN(cwpath), sub_root->name_ptr, sub_root->name_leng, MAX_PATH);
TS_CHDIR(cwpath);
}
break;
case NFA_IS_TERMINATE_CURR:
// 这个case下面的还没调试过,暂时采用NFA_IS_ENTRY_PARENT同样的处理
DBG_PRINT("==>NFA_IS_TERMINATE_CURR\n");
cwpath_ret_level = 0;
do
{
find_upper = FALSE;
cwpath_ret_level += 1;
if(sub_root == NULL)
{
loop_next = FALSE;
}
else if (sub_root->prev_brother_ptr != NULL)
{
to_be_del = sub_root;
sub_root = sub_root->prev_brother_ptr;
}
else
{
if(sub_root->parent_ptr != NULL)
{
DBG_PRINT("find_upper: sub_root->parent = %s.\n", sub_root->parent_ptr->name_ptr);
}
to_be_del = sub_root;
sub_root = sub_root->parent_ptr;
find_upper = TRUE;
}
}while(find_upper);
/* 如果到了*节点,注意删除后将指针设置成空 */
if(to_be_del == *rootp)
{
ts_delete_node(&to_be_del);
//注意将指针设置成NULL
*rootp = NULL;
}
else
{
ts_delete_node(&to_be_del);
}
if(loop_next)
{
//要修正下路径,否则查找会失败的
ts_path_back(cwpath, TS_STRLEN(cwpath), cwpath_ret_level);
ts_path_combine(cwpath, TS_STRLEN(cwpath), sub_root->name_ptr, sub_root->name_leng, MAX_PATH);
TS_CHDIR(cwpath);
}
break;
case NFA_IS_EXIT_SEARCH:
MSG_SHOW("The last search returned NFA_IS_EXIT_SEARCH, stop all search!\n");
ts_delete_node(rootp);
//注意将指针设置成NULL
to_be_del = NULL;
*rootp = NULL;
ret_val = PROG_RET_PROG_TERMINATE;
loop_next = FALSE;
break;
default:
MSG_SHOW("The last search returned a unknown error, stop all search!\n");
ts_delete_node(rootp);
//注意将指针设置成NULL
to_be_del = NULL;
*rootp = NULL;
ret_val = PROG_RET_UNKNOWN_ERR;
loop_next = FALSE;
break;
}
} while (loop_next);
exit_func:
return ret_val;
}
#3
其中,为了检测内存泄露,特地使用一个函数,改装内存的申请与释放过程,代码如下:
#if defined(MEM_LEAK_CHECK)
static long int memoryUsedMax = 0;
static long int memoryUsedCur = 0;
static MEM_LEAK_T *memLeakListPtr = NULL;
static void* ts_alloc_with_mem_check(size_t memsize)
{
void *allocated_mem_ptr = NULL;
register MEM_LEAK_T *newnode = NULL;
register MEM_LEAK_T *prevnode = NULL;
register MEM_LEAK_T *currnode = memLeakListPtr;
allocated_mem_ptr = (void*)TS_MALLOC(memsize);
if(allocated_mem_ptr != NULL)
{
newnode = (MEM_LEAK_T*)TS_MALLOC(sizeof(MEM_LEAK_T));
if(newnode != NULL)
{
/* 申请一个新的节点,记录内存申请信息,插入链表 */
newnode->memAdr = (int)allocated_mem_ptr;
newnode->memSize = memsize;
newnode->next = NULL;
while(currnode != NULL)
{
prevnode = currnode;
currnode = currnode->next;
}
if(prevnode == NULL)
{
memLeakListPtr = newnode;
}
else
{
prevnode->next = newnode;
}
memoryUsedCur += (memsize + sizeof(MEM_LEAK_T));
if(memoryUsedMax<memoryUsedCur)
{
memoryUsedMax = memoryUsedCur;
}
}
}
else
{
MEM_PRINT("ts_alloc_with_mem_check FAILED!\n");
}
return allocated_mem_ptr;
}
static void ts_free_with_mem_check(void* memPtr)
{
register MEM_LEAK_T *currnode = memLeakListPtr;
register MEM_LEAK_T *prevnode = NULL;
while(currnode != NULL)
{
if(currnode->memAdr == (int)memPtr)
{
break;
}
else
{
prevnode = currnode;
currnode = currnode->next;
}
}
TS_FREE(memPtr);
if(currnode != NULL)
{
memoryUsedCur -= (currnode->memSize + sizeof(MEM_LEAK_T));
if(prevnode != NULL)
{
prevnode->next = currnode->next;
currnode->next = NULL;
TS_FREE(currnode);
currnode = NULL;
}
else
{
/* the head of list */
if(currnode->next == NULL)
{
TS_FREE(currnode);
currnode = NULL;
memLeakListPtr = NULL;
}
else
{
memLeakListPtr = currnode->next;
currnode->next = NULL;
TS_FREE(currnode);
currnode = NULL;
}
}
}
}
static void ts_mem_check_at_prog_exit(void)
{
int no_memory_leak_flag = TRUE;
register MEM_LEAK_T *currnode = memLeakListPtr;
register MEM_LEAK_T *prevnode = NULL;
while(currnode != NULL)
{
MEM_PRINT("\nmemory leaked at 0x%08x, size is %4d bytes.", currnode->memAdr, currnode->memSize);
prevnode = currnode;
currnode = currnode->next;
TS_FREE((void*)(prevnode->memAdr));
TS_FREE(prevnode);
no_memory_leak_flag = FALSE;
}
if(no_memory_leak_flag)
{
MEM_PRINT("There is no memory leak. memoryUsedCur=%d.\n",memoryUsedCur);
MSG_SHOW("memoryUsedMax=%d.\n",memoryUsedMax);
}
}
#endif /*defined(MEM_LEAK_CHECK)*/
#4
不错 如果是我我会选择用树来实现
#5
请问,如果用树来实现的话,其基本思路是怎样的呢?
我没学过数据结构,很多东西都不太理解。希望你能稍微做点提醒,得空我再研究下树的实现。
#6
刚才去百度了下,你说的树,指的是二叉树吧?深度优先搜索和广度优先搜索,是不?这两个算法的概念我看了下,但是没有确切的实践,始终没法理解透彻,也没法实际应用。不知道你能否开个贴,示意部分代码,参考学习下呢?
#7
[liangdong@bb-browser-test00.vm.baidu.com c_project]$ make
gcc -g -I. -I../libs/include -c -o main.o main.c
gcc -o main main.o
[liangdong@bb-browser-test00.vm.baidu.com c_project]$ ./main
/home/liangdong/c_project/main.c
楼主辛苦了。
#8
NAME
glob, globfree - find pathnames matching a pattern, free memory from glob()
SYNOPSIS
#include <glob.h>
int glob(const char *pattern, int flags,
int errfunc(const char *epath, int eerrno),
glob_t *pglob);
void globfree(glob_t *pglob);
NAME
realpath - return the canonicalized absolute pathname
SYNOPSIS
#include <limits.h>
#include <stdlib.h>
char *realpath(const char *path, char *resolved_path);
#9
[liangdong@bb-browser-test00.vm.baidu.com c_project]$ cat main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
int main(int argc, char* const argv[]) {
char path[PATH_MAX];
if (realpath("./main.c", path) != NULL) {
printf("%s\n", path);
}
return 0;
}
忘了贴代码。
#10
你用代码描述了这么多,好像,没有说明什么,我去百度了一下,你调用的这个函数好像是用来获取文件的绝对路径的。
realpath()用来将参数path所指的相对路径转换成绝对路径后存于参数resolved_path所指的字符串数组或指针中 返回值: 成功则返回指向resolved_path的指针,失败返回NULL,错误代码存于errno
这似乎跟遍历文件夹的联系不大啊。
#11
还是觉得递归比较好用。
#12
system("dir /b /s /a-d c:\\*.* >d:\\allfiles.txt");
//读文件d:\\allfiles.txt的内容即C:\\下所有文件的绝对路径
请记住,能用shell命令获取文件、文件夹信息或者操作文件、文件夹最好用shell命令获取或者操作,而不要用各种API获取或者操作,因为当遇到非法文件夹名或非法文件名或非法文件长度、非法文件日期、压缩文件、链接文件、稀疏文件……等各种意料之外的情况时,API会处理的不全面或陷入死循环,而shell命令不会。
//读文件d:\\allfiles.txt的内容即C:\\下所有文件的绝对路径
请记住,能用shell命令获取文件、文件夹信息或者操作文件、文件夹最好用shell命令获取或者操作,而不要用各种API获取或者操作,因为当遇到非法文件夹名或非法文件名或非法文件长度、非法文件日期、压缩文件、链接文件、稀疏文件……等各种意料之外的情况时,API会处理的不全面或陷入死循环,而shell命令不会。
#13
大佬,又看到你来顶我的帖子了。我记得我以前提这个问题的时候你就是这么指导的。你说的很对。
我在编写这个程序的时候还在担心如果碰到unicode字符的文件名的时候,我的strlen, strcpy还有效么?
庆幸的是,我在VC6下测试,暂时没发现什么异常。想来是VC6里面的库支持unicode吧。
通过这个实践,我对之前学习C语言的链表的内容有了很大程度掌握。这个才是关键!
谢谢你的指导!
#14
试想如果你的文件夹深度在8纪以上,文件夹数量上万,文件的数量也上万,此时,来用用你的递归,是否存在局限呢?
#15
楼主,威武,代码………………