ls -r

这篇博客继续深入探索ls命令。下面的程序代码继续沿用了上两篇文章所用的错误处理方式,但又对之前的错误处理进行了升级,加入了错误处理函数error_print 。并且通过atexit函数加入了动态分配内存的收集与处理。
由于我的编译环境在终端,每一行只能显示80个字符,所以有些语句太长我该成了两行。

// lsr.h
#ifndef LSR
#define LSR#include <stdio.h>   // printf()
#include <unistd.h>  // getcwd()
#include <string.h>  // strlen() strcpy() strcat() memset()
#include <stdlib.h>  // exit() malloc() free() atexit()
#include <dirent.h>  // opendir() closedir() readdir()typedef struct FileInfoList {              // 使用链表存储char *name;                        // 存储文件/文件夹名struct FileInfoList *dir;          // 当name存储文件名时为空 // 当name存储文件夹名时指向文件夹中的文件struct FileInfoList *file;          // 指向下一个(next)
} file_info_list;                  file_info_list head;                       // 全局变量 头节点// 这个结构体作为链表节点存储动态内存分配后需要释放的动态内存空间
typedef struct NeedFreeList {char *ptr;                       // 需要free的指针struct NeedFreeList *next;       // 下一个
} need_free_list;need_free_list *begin = NULL;            // 全局变量 开头指针typedef enum ERROR {                     // 各种错误信息ERROR_CODE_OK,ERROR_CODE_MALLOC_GETPATH,ERROR_CODE_MALLOC_COLLECT,ERROR_CODE_GETCWD,ERROR_CODE_OPENDIR,ERROR_CODE_COLLECT,ERROR_CODE_MALLOC_NODE,ERROR_CODE_MALLOC_NAME,ERROR_CODE_MALLOC_DIRPATH
} error;error malloc_collect(char *);                 // 动态内存分配后收集需要free的动态内存指针
void clear(void);                             // 终止处理程序
void error_print(error);                      // 错误信息输出
error getpath(char**);                        // 得到路径
error filename_collect(char*, file_info_list*);     // 文件名收集函数 (递归)
void sort(file_info_list*, file_info_list*);        // 将节点插入链表中并保持有序
void print(file_info_list*, int);                   // 输出以head为头节点存储的文件/文件夹名#endif

下面时 .c 文件,包含具体的函数实现

// lsr.c
#include "lsr.h"//#define TESTint main(void)
{atexit(clear);                    // 登记clear这个终止处理程序char *path;error errcode = getpath(&path);     // 得到当前路径 实参是指针path的地址 不是pathif (errcode == ERROR_CODE_OK) {#ifdef TESTprintf("%s\n", path);
#endiferrcode = filename_collect(path, &head);     // 文件/文件名收集存储if (errcode == ERROR_CODE_OK) {printf("%s :\n", path);print(head.dir, 1);                 // 打印出文件/文件名}}error_print(errcode);                   // 如果出错 则输出错误信息exit(0);      // exit函数调用了clear这个终止处理程序 进行动态内存释放
}void error_print(error errcode)
{switch (errcode) {    // 各种错误信息case ERROR_CODE_OK :break;case ERROR_CODE_MALLOC_GETPATH :printf("in the function of getpath, malloc error!\n");break;case ERROR_CODE_MALLOC_COLLECT :printf("in the function of collect, malloc error!\n");break;case ERROR_CODE_GETCWD :printf("in the function of getpath, getcwd error!\n");break;case ERROR_CODE_OPENDIR :printf("in the function of filename_collect, ""opendir error!\n");break;case ERROR_CODE_MALLOC_NODE :printf("in the function of filename_collect, ""node space malloc error!\n");break;case ERROR_CODE_MALLOC_NAME :printf("in the function of filename_collect, ""name space malloc error!\n");break;case ERROR_CODE_MALLOC_DIRPATH :printf("in the function fo filename_collect, ""dirpath space malloc error!\n");break;default :break;}return;
}void print(file_info_list *beg, int num)
{while (beg != NULL) {       for (int i = 0; i < num; ++i)printf("\t");         // 使输出更加直观printf("%s", beg->name);if (beg->dir != NULL) {printf(" :\n");print(beg->dir, num+1);} else {printf("\n");}beg = beg->file;}return;
}void sort(file_info_list *node, file_info_list *ptr)
{if (ptr->dir == NULL) {      // 加入第一个节点ptr->dir = node;return;}if (strcmp(ptr->dir->name, node->name) > 0) {    // 文件/文件夹名最小 需要排在最前node->file = ptr->dir;ptr->dir = node;return;}file_info_list *next = ptr->dir; while (next->file != NULL) {if (strcmp(next->file->name, node->name) > 0) {node->file = next->file;next->file = node;return;}next = next->file;    // file可能不太好理解 想像成next就好了}next->file = node;      // 文件/文件名最大需要排在最后return;
}error filename_collect(char *path, file_info_list *beg)
{DIR *dir;if ((dir = opendir(path)) == NULL)return ERROR_CODE_OPENDIR;struct dirent *dent;while ((dent = readdir(dir)) != NULL) {if (strcmp(dent->d_name, ".") == 0 ||strcmp(dent->d_name, "..") == 0)continue;      // .和..不存储 也不输出file_info_list *node =(file_info_list*)malloc(sizeof(file_info_list));if (node == NULL)return ERROR_CODE_MALLOC_NODE;memset(node, 0, sizeof(file_info_list)); // 必须要调用这个函数进行清0// 为了使node->file为NULL 不然程序出错node->name =(char*)malloc((strlen(dent->d_name)+1)*sizeof(char));if (node->name == NULL) {free(node);return ERROR_CODE_MALLOC_NAME;}strcpy(node->name, dent->d_name);sort(node, beg);              // 将node加入链表中并保持链表有序if (dent->d_type == DT_DIR) {    // 当是文件夹时 递归char *dirpath = (char*)malloc(256*sizeof(char));  // 存储新路径if (dirpath == NULL)return ERROR_CODE_MALLOC_DIRPATH;memset(dirpath, 0, 256);error errcode = malloc_collect(dirpath);  // 将动态内存分配后得到的指针存储 以便清理   if (errcode != ERROR_CODE_OK)return errcode;   strcpy(dirpath, path);strcat(dirpath, "/");strcat(dirpath, dent->d_name);filename_collect(dirpath, node);   // 进入递归}
#ifdef TESTprintf("%d ", dent->d_reclen);     // 测试所用代码 printf("%s\n", node->name);
#endif}closedir(dir);return ERROR_CODE_OK;
}error getpath(char **pathptr)   // 注意这个是二级指针 是一级指针path的地址
{*pathptr = (char*)malloc(256*sizeof(char));if (*pathptr == NULL)return ERROR_CODE_MALLOC_GETPATH;error errcode = malloc_collect(*pathptr);    //将动态内存分配后得到的指针存储 以便清理if (errcode != ERROR_CODE_OK)return errcode;memset(*pathptr, 0, 256);if (getcwd(*pathptr, 256) != *pathptr)   // 获得当前路径return ERROR_CODE_GETCWD;return ERROR_CODE_OK;
}error malloc_collect(char *str)
{need_free_list *node_p =(need_free_list*)malloc(sizeof(need_free_list));if (node_p == NULL)return ERROR_CODE_COLLECT;memset(node_p, 0, sizeof(need_free_list));node_p->ptr = str;     // 头插法node_p->next = begin;begin = node_p;return ERROR_CODE_OK;
}void clear(void)    // 返回值和参数必须为void
{while (begin != NULL) {    // begin为全局变量 定义和初始化在头文件中
#ifdef TESTprintf("path space free : %s\n", begin->ptr);
#endifneed_free_list *net = begin->next;   free(begin->ptr);free(begin);begin = net;}return;
}

linux系统下ls -r命令的简单实现(C语言版)相关推荐

  1. linux中split分割文件打开方式,Linux系统下使用split命令分割大文件 (转载)

    [小蜗牛闲情之作 ] 我想给一个朋友传一个大视频,有几百M,尝试多种传输办法失败后,最后想到的是把视频切开一片片"邮递"过去给他,让它自己组装起来吧. [root@pps publ ...

  2. linux文件分割命令性能,Linux系统下使用split命令分割大文件 (转载)

    [小蜗牛闲情之作 ] 我想给一个朋友传一个大视频,有几百M,尝试多种传输办法失败后,最后想到的是把视频切开一片片"邮递"过去给他,让它自己组装起来吧. [root@pps publ ...

  3. Windows-Linux:Windows系统下的命令类似Linux系统下的所有命令集合

    Windows-Linux:Windows系统下的命令类似Linux系统下的所有命令集合 目录 Windows下的命令类似Linux系统下的所有命令集合 1.基础命令 2.进阶命令 3.高级命令 Wi ...

  4. dd linux 格式化u盘启动盘_在Linux系统下用DD命令制作ISO镜像U盘启动盘

    穆僮电脑小课堂 (QQ群:141826908)摘编整理 ​我的当前的系统是Linux(版本Xubuntu),之前是通过软通牒(UltraISO)在Windows系统下制作了这个Linux系统的U盘启动 ...

  5. Linux ss 热点,在Linux系统下的ss命令(socket statistics)各种使用示例

    本文演示在Linux操作系统下的ss命令(socket statistics)的各种使用示例.ss(套接字统计信息)是一个命令行工具,用于监视套接字连接并显示Linux系统的套接字统计信息.它可以显示 ...

  6. linux的top命令cpu,在Linux系统下使用top命令查看CPU使用情况

    在Linux系统下,使用top命令查看CPU使用情况. %Cpu(s): 0.3 us, 0.1 sy, 0.0 ni, 99.6 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st ...

  7. linux系统下修改文件命令vi的使用

    在linux系统下,vi的使用时非常频繁.非常正规的,掌握vi的使用技巧大有裨益 例如,我要修改etc目录下的文件profile的内容 vi /etc/profile---更改profilr下的内容 ...

  8. Linux系统下定时关机命令shutdown

    接触过linux系统的都知道shutdown命令用于安全的关闭/重启计算机,用决定命令shutdown不仅可以实现定时关机,还可以由用户自己决定关机时的参数:以下简单了解一下同样的功能在linux下使 ...

  9. linux系统怎么ping命令,Linux系统下的ping命令的使用

    学习计算机网络的时候,常用的网络诊断工具比如ping.ipconfig命令这些都是我们经常要使用的,主要是用来监测网络是否通顺,相信你在Windows中已经是有经常使用过,并且也可以在dos系统下面可 ...

最新文章

  1. PyTorch ToTensor解读
  2. 演讲预告:一个月的住院经历,我悟到了哪些和程序员职场发展相关的心得
  3. react native项目改名(仅针对android)
  4. rsync 3.1.1源代码编译安装配置
  5. 编程建立一通讯簿C语言,C语言编程问题用C语言编个学生通讯录管理系统,功能有:①创建通讯 爱问知识人...
  6. 第三章:3.8 登陆 Django 默认后台
  7. 配置 MAC地址表实现绑定和过滤
  8. EPLAN史上最全部件库,部件宏,EDZ格式
  9. 我有几张阿里云幸运券分享给你,用券购买或者升级阿里云相应产品会有特惠惊喜哦!把想要买的产品的幸运券都领走吧!快下手,马上就要抢光了。
  10. vue 动态渲染表格序号列
  11. matlab里方框一个叉号,怎么在word文档里添加小方框中打叉的符号
  12. java实现图片查看器
  13. Android7.0 PowerManagerService(4) Power按键流程
  14. 单条件求和和多条件求和以及条件求平均
  15. 计算机oa学些什么,OA是什么意思?OA可以干什么 -电脑资料
  16. java 知网 语义 相似度,基于知网语义相似度的中文文本分类研究 论文笔记
  17. java根据word模板导出_java根据模板生成,导出word和pdf(aspose.words实现word转换pdf)...
  18. mysql 汉字一排序规则_MySQL 的字符集与排序规则
  19. (十)Intellij 远程调试 a bug
  20. 网络爬虫(网络蜘蛛,网络机器人)与Web安全

热门文章

  1. 电容ESR表(一) 电容ESR表的特点、测量原理、电路分析
  2. freemarker实现word模板
  3. 使用ajax和window.history.pushState无刷新改变页面内容和地址栏URL
  4. Flash 多人在线游戏教程 - TicTacToe
  5. 计算机毕业设计Java国漫论坛网站(源码+系统+mysql数据库+Lw文档)
  6. EDM邮件群发:群发邮件不进垃圾箱的独家秘笈
  7. JSoup模拟登录新版正方教务系统(内网-教务系统)获取信息过程详解
  8. php下雨效果源码,ps下雨效果制作步骤
  9. MiKTeX安装及添加到环境变量
  10. 8、ABPZero系列教程之拼多多卖家工具 添加手机注册登录功能