请给这段代码每行注释
时间: 2024-11-25 07:08:13 浏览: 4
Dreamweaver怎么给代码添加注释?
以下是带有逐行注释的代码:
```c
#include <stdio.h> // 引入标准输入输出头文件
#include <string.h> // 引入字符串处理函数头文件
#include <unistd.h> // 引入 POSIX 操作系统 API 头文件
#include <dirent.h> // 引入目录操作头文件
#include <errno.h> // 引入错误号定义头文件
#include <sys/stat.h> // 引入文件状态相关函数头文件
#include <sys/types.h> // 引入基本系统数据类型头文件
#include <time.h> // 引入时间处理函数头文件
// 定义关闭目录指针的辅助函数
void check_and_close_dir(DIR *dp) {
if (dp != NULL) { // 如果目录指针不为空
closedir(dp); // 关闭目录
}
}
// 创建目录的函数
void create_dir(char* pathname, mode_t mode) {
int rval = mkdir(pathname, mode); // 调用 mkdir 函数创建目录
if (rval == -1) { // 如果创建失败
perror("创建文件夹失败"); // 打印错误信息
}
}
// 删除目录及其子目录和文件的递归函数
void rm_dir(char* pathname) {
DIR *dp = opendir(pathname); // 打开目录
if (dp == NULL) { // 如果打开失败
printf("打开文件夹失败。errno: %d\n", errno); // 打印错误信息并返回
return;
}
struct dirent *dirp; // 声明目录项结构体指针
while ((dirp = readdir(dp)) != NULL) { // 遍历目录中的每个条目
if (strcmp(dirp->d_name, "..") == 0 || strcmp(dirp->d_name, ".") == 0) {
continue; // 忽略当前目录(.)和父目录(..)
}
char subpathname[256]; // 子路径缓冲区
snprintf(subpathname, sizeof(subpathname), "%s/%s", pathname, dirp->d_name); // 构建子路径
struct stat sb; // 声明文件状态结构体
if (stat(subpathname, &sb) == -1) { // 获取子路径的状态
printf("无法获取 %s 的状态\n", subpathname); // 如果获取失败,打印错误信息并继续下一个条目
continue;
}
if (S_ISDIR(sb.st_mode)) { // 如果是目录
rm_dir(subpathname); // 递归调用删除子目录
} else { // 否则为文件
if (remove(subpathname) == -1) { // 尝试删除文件
printf("%s 删除失败\n", subpathname); // 如果删除失败,打印错误信息
}
}
}
check_and_close_dir(dp); // 关闭目录指针
if (rmdir(pathname) == -1) { // 尝试删除空目录
printf("%s 删除失败\n", pathname); // 如果删除失败,打印错误信息
}
}
// 移动目录的函数
void move_dir(char* src, char* dest) {
struct stat dest_stat; // 声明目标目录状态结构体
if (stat(dest, &dest_stat) != -1) { // 检查目标目录是否存在
fprintf(stderr, "目标目录 '%s' 已存在。\n", dest); // 如果存在,打印错误信息并返回
return;
}
if (rename(src, dest) == -1) { // 尝试重命名源目录为目标目录
perror("移动目录失败"); // 如果失败,打印错误信息
}
}
// 计算目录大小的递归函数
long get_dir_size(char* pathname) {
long total_size = 0; // 初始化总大小为0
DIR *dp = opendir(pathname); // 打开目录
if (dp == NULL) { // 如果打开失败
perror("无法打开目录"); // 打印错误信息并返回0
return total_size;
}
struct dirent *dirp; // 声明目录项结构体指针
struct stat sb; // 声明文件状态结构体
while ((dirp = readdir(dp)) != NULL) { // 遍历目录中的每个条目
if (strcmp(dirp->d_name, "..") == 0 || strcmp(dirp->d_name, ".") == 0) {
continue; // 忽略当前目录(.)和父目录(..)
}
char subpathname[256]; // 子路径缓冲区
snprintf(subpathname, sizeof(subpathname), "%s/%s", pathname, dirp->d_name); // 构建子路径
if (stat(subpathname, &sb) == -1) { // 获取子路径的状态
perror("stat失败"); // 如果获取失败,打印错误信息并继续下一个条目
continue;
}
if (S_ISDIR(sb.st_mode)) { // 如果是目录
total_size += get_dir_size(subpathname); // 递归计算子目录大小并累加到总大小中
} else { // 否则为文件
total_size += sb.st_size; // 累加文件大小到总大小中
}
}
check_and_close_dir(dp); // 关闭目录指针
return total_size; // 返回总大小
}
// 显示目录信息的函数
void display_dir_info(char* pathname) {
struct stat sb; // 声明文件状态结构体
if (stat(pathname, &sb) == -1) { // 获取目录状态
perror("stat失败"); // 如果获取失败,打印错误信息并返回
return;
}
long size = get_dir_size(pathname); // 计算目录大小
char timebuf[100]; // 时间格式化缓冲区
strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S", localtime(&sb.st_mtime)); // 格式化修改时间
printf("文件夹: %s\n", pathname); // 输出目录名称
printf("大小: %ld B (%.2f KB | %.2f MB | %.2f GB)\n", size, size / 1024.0, size / (1024.0 * 1024.0), size / (1024.0 * 1024.0 * 1024.0)); // 输出目录大小
printf("修改时间: %s\n", timebuf); // 输出修改时间
printf("权限: %o (用户: %o, 组: %o, 其他: %o)\n", sb.st_mode & 0777, (sb.st_mode & 0700) >> 6, (sb.st_mode & 0070) >> 3, (sb.st_mode & 0007)); // 输出权限信息
}
// 打印帮助信息的函数
void print_help() {
printf("Usage: \n"); // 打印使用说明
printf("创建一个新文件夹: dir_ops -n pathname \n");
printf("删除一个新文件夹: dir_ops -d pathname \n");
printf("重命名一个新文件夹: dir_ops -r old_pathname new_pathname \n");
printf("移动一个文件夹: dir_ops -m src_pathname dest_pathname \n");
printf("显示文件夹信息: dir_ops -info pathname\n");
}
// 主函数
int main(int argc, char const *argv[]) {
mode_t mode = 0777; // 设置默认权限为 0777(所有权限)
int op_mode = 0; // 初始化操作模式变量
if (argc > 1) { // 如果有命令行参数
if (strcmp(argv[1], "-n") == 0) { // 检查是否为创建目录操作
op_mode = 1;
} else if (strcmp(argv[1], "-d") == 0) { // 检查是否为删除目录操作
op_mode = 2;
} else if (strcmp(argv[1], "-r") == 0) { // 检查是否为重命名目录操作
op_mode = 3;
} else if (strcmp(argv[1], "-m") == 0) { // 检查是否为移动目录操作
op_mode = 4;
} else if (strcmp(argv[1], "-info") == 0) { // 检查是否为显示目录信息操作
op_mode = 5;
} else { // 未知操作
print_help(); // 打印帮助信息
return 0;
}
} else { // 没有命令行参数
print_help(); // 打印帮助信息
return 0;
}
switch (op_mode) { // 根据操作模式执行相应操作
case 1:
if (argc > 2) { // 检查是否有目录路径参数
char* pathname = argv[2];
create_dir(pathname, mode); // 调用创建目录函数
}
break;
case 2:
if (argc > 2) { // 检查是否有目录路径参数
char* pathname = argv[2];
rm_dir(pathname); // 调用删除目录函数
}
break;
case 3:
if (argc > 3) { // 检查是否有旧路径和新路径参数
char* oldpath = argv[2];
char* newpath = argv[3];
if (rename(oldpath, newpath) == -1) { // 调用 rename 函数重命名目录
perror("重命名失败"); // 如果失败,打印错误信息
}
}
break;
case 4:
if (argc > 3) { // 检查是否有源路径和目标路径参数
char* src = argv[2];
char* dest = argv[3];
move_dir(src, dest); // 调用移动目录函数
}
break;
case 5:
if (argc > 2) { // 检查是否有目录路径参数
char* pathname = argv[2];
display_dir_info(pathname); // 调用显示目录信息函数
}
break;
default:
break;
}
return 0; // 返回0表示程序正常结束
}
```
希望这些注释能帮助你更好地理解代码的功能和实现细节。如果有任何进一步的问题,请随时告诉我!
阅读全文