递归调用
C/C++中函数是可以调用自己的,这种操作就是递归调用。递归调用在一些使用场景下可以大大的简化代码。但递归调用也存在一些不足,对于程序员来讲,递归调用会降低代码的可读性,对于机器来讲,递归调用的嵌套越深的话,就会占用更多的栈区域。
递归调用可以有效的解决很多问题,由于其占用了较大的栈空间,根据空间与效率的原理,递归调用具有较高的执行效率,因此在对较大数据进行遍历时使用这个方法可以获得较高的速度。
要是用递归调用必须保证两点
1. 有明确的边界条件;
2. 有明显的前后关系。
递归的适用场景
最简单的递归就是计算一个数列的和值:
int a_add_to_b(int a, int b)
{
if(a != b)
{
return a + a_add_to_b(a + 1, b);
}
else
{
return a;
}
}
当然除了和值,计算阶乘、差比数列等等都是可行的。
对具有树状结构的数据进行搜索:
对于遍历具有树结构的数表时可以只用递归调用的方法。典型的应用就是对目录的搜索。
我们知道Linux的文件是一“/”为根,然后成树状组织的,我们要在这些目录下查找一个文件使用递归调用的方法将非常的方便。
以下是代码实现:
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
typedef struct _FILEDOCNUM{
unsigned int filenum;
unsigned int docnum;
}FILEDOCNUM;
FILEDOCNUM filedocnum = {0, 0};
int find_all_dir_file(const char *base_path)
{
DIR *dir = NULL; ///>路径信息
char path[1024] = {0}; ///>拷贝当前进入目录
char enter_path[1024] = {0}; ///>进入的下级目录
//拷贝当前进入目录
strcpy(path, base_path);
//打开目录
dir = opendir(path);
//判断是否成功打开了目录
if(dir == NULL)
{
printf("open dir failed\r\n");
return 0;
}
//打开成功
//读取目录下所有的文件夹和文件名称
struct dirent *_dirent = NULL;// = readdir(dir);
do
{
//读取当前目录下的一个文件或文件夹信息
_dirent = readdir(dir);
//到达当前目录末尾,跳出循环
if(NULL == _dirent)
{
break;
}
//判断类型,如果是文件则打印目录,如果是目录则迭代进入查找
if(DT_DIR == _dirent->d_type)
{
//如果是当前目录或是上级目录则跳过,否则进入目录迭代查找
if(0 == strcmp(_dirent->d_name, ".") || 0 == strcmp(_dirent->d_name, ".."))
{
continue;
}
else
{
strcpy(enter_path, path);
strcat(enter_path, _dirent->d_name);
strcat(enter_path, "/");
filedocnum.docnum++;
printf("%s\r\n", enter_path);
find_all_dir_file(enter_path);
}
}
else
{
filedocnum.filenum++;
printf("%s%s\r\n", path, _dirent->d_name);
}
}while(_dirent != NULL);
if(dir != NULL)
{
closedir(dir);
}
return 0;
}
int main(int arg, char *argc[])
{
char path[1024];
//如果传入了指定目录则按照指定目录所搜,如果没有指定目录则按当前目录搜索
if(argc[1] != NULL)
{
strcpy(path, argc[1]);
}
else
{
strcpy(path, "./");
}
printf("begin to scan all file and path\r\n");
find_all_dir_file(path);
printf("scan completed, there are %d file(s) and %d document(s) total: %d\r\n", \
filedocnum.filenum, filedocnum.docnum, filedocnum.filenum + filedocnum.docnum);
return 0;
}
以上代码实现的功能是,分别统计指定目录下的文件数和目录数,最后输出。