方法一:递归
代码思路:
1. 定义一个函数`count_files_and_folders`,该函数接受一个目录路径参数,并使用指针引用来传递文件和文件夹数量的统计结果。
2. 在函数内部,使用`opendir`函数打开指定的目录,如果打开失败,输出错误信息并返回。
3. 使用`readdir`函数按顺序读取目录中的每个文件和文件夹。
4. 对于每个读取到的文件和文件夹,先判断是否为`.`或`..`,如果是则跳过。否则,将文件/文件夹名称和目录路径拼接成完整的路径。
5. 使用`stat`函数获取文件/文件夹的详细信息,如果获取失败,输出错误信息并继续处理下一个。
6. 根据文件/文件夹的类型(使用宏`S_ISDIR`判断是否是文件夹),分别做如下处理:
- 如果是文件夹,则增加文件夹数量,并递归调用`count_files_and_folders`函数,传入当前文件夹的路径,以及文件和文件夹的数量引用。
- 如果是文件,则增加文件数量。
7. 使用`closedir`函数关闭目录。
8. 在`main`函数中,首先定义文件和文件夹数量的变量。
9. 获取用户输入的指定目录路径。
10. 调用`count_files_and_folders`函数,传入指定目录路径和文件/文件夹数量引用。
11. 输出统计结果。
请注意,缩进和格式只是为了增加代码的可读性,并在不同部分之间代码块之间添加了注释解释。在实际编写中,可以根据自己的习惯和代码风格进行调整。
方法二:多线程
代码思路:
1. 首先,在主函数中指定要搜索的目录。这个目录将被传递给每个线程进行搜索。
2. 初始化互斥锁,用于保护共享的计数器变量。
3. 创建线程数组和参数数组,用于保存线程和参数。
4. 使用一个循环,创建一定数量(64个)的线程,并将搜索目录作为参数传递给每个线程。
5. 在线程函数`search_files_and_directories()`中,首先获取传递的目录路径。
6. 使用`opendir()`函数打开目录,并检查是否成功打开。
7. 在循环中,使用`readdir()`函数读取目录中的每个条目(文件或子目录)。
8. 对于每个条目,构建完整的路径,并根据其类型决定是增加子目录计数还是增加文件计数。
9. 如果是子目录,则递归调用`search_files_and_directories()`函数进行进一步的搜索。
10. 处理完当前目录的所有条目后,使用`closedir()`函数关闭目录。
11. 在主函数中使用`pthread_join()`函数等待所有线程完成。
12. 销毁互斥锁。
13. 输出最终的子目录和文件数量。
总体上,程序使用多线程的方式并行搜索指定目录下的文件和子目录。通过使用互斥锁来保护计数器变量的访问,确保线程之间的安全访问。
每个线程负责搜索目录中的一部分内容,并更新共享计数器变量的值。通过递归调用,线程可以深入搜索子目录。
最后,主线程等待所有线程完成,并输出最终的结果。
#include <stdio.h>
#include <dirent.h>
#include <pthread.h>
#include <string.h>
#define MAX_THREADS 64
#define MAX_PATH_LENGTH 1024
struct ThreadArgs {
char path[MAX_PATH_LENGTH]; // 存储目录路径
int file_count; // 存储文件数量
int folder_count; // 存储文件夹数量
};
void* search_files_and_directories(void* arg) {
struct ThreadArgs* args = (struct ThreadArgs*)arg;
char* path = args->path;
int* file_count = &(args->file_count);
int* folder_count = &(args->folder_count);
DIR* directory;
struct dirent* entry;
directory = opendir(path); // 打开目录
if (directory == NULL) {
printf("Unable to open directory: %s\n", path);
pthread_exit(NULL);
}
while ((entry = readdir(directory)) != NULL) { // 遍历目录下的条目
if (entry->d_type == DT_DIR) { // 如果是文件夹
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
(*folder_count)++; // 增加文件夹数量
char sub_path[MAX_PATH_LENGTH];
snprintf(sub_path, sizeof(sub_path), "%s/%s", path, entry->d_name); // 构建子目录路径
search_files_and_directories(sub_path); // 递归搜索子目录
}
} else if (entry->d_type == DT_REG) { // 如果是文件
(*file_count)++; // 增加文件数量
}
}
closedir(directory); // 关闭目录
pthread_exit(NULL);
}
int main(int argc, char* argv[]) {
if (argc != 2) {
printf("Usage: %s <directory>\n", argv[0]);
return 0;
}
char* path = argv[1];
int total_file_count = 0;
int total_folder_count = 0;
pthread_t threads[MAX_THREADS];
struct ThreadArgs thread_args[MAX_THREADS];
// 初始化线程参数
for (int i = 0; i < MAX_THREADS; i++) {
strcpy(thread_args[i].path, path);
thread_args[i].file_count = 0;
thread_args[i].folder_count = 0;
}
// 创建线程
for (int i = 0; i < MAX_THREADS; i++) {
pthread_create(&threads[i], NULL, search_files_and_directories, (void*)&thread_args[i]);
}
// 等待线程完成
for (int i = 0; i < MAX_THREADS; i++) {
pthread_join(threads[i], NULL);
total_file_count += thread_args[i].file_count;
total_folder_count += thread_args[i].folder_count;
}
printf("Total number of files: %d\n", total_file_count);
printf("Total number of folders: %d\n", total_folder_count);
return 0;
}