C语言测试。自己实现scandir 函数

article/2025/9/28 14:21:16
在C语言课程的后端,讲完指针和标准文件IO处理,我会做出一个难度较大练习,题目就是, 利用标准的目录处理函数 opendir/readdir/closedir实现类似于 scandir的功能。其中接口要scandir 函数一致
这个题目看起来简单,实现难度相当大,主要采用复杂指针的操作。我第一次拿出来测试,全班大约只一二名实现80%的功能,其余很多觉得无从下手。程序很容易就会出现段错误。基本上短时间内正确的做出来的人可以划归专业级的程度了。有兴趣的人可以先不看后面内容,自行实现一下。
首先看一下man的scandir 接口定义
int scandir(const char *dir, struct dirent ***namelist,
              int(*filter)(const struct dirent *),
              int(*compar)(const struct dirent **, const struct dirent **));
,从定义来看就不是一个简单的函数,形参里,出现一个三级指针,二个函数指针。它的功能是,扫描名字为dir的目录,把满足filter函数的过滤条件(即filter执行为非0值)的目录项加入到一维指针数组namelist.数组的总长度为返回值n,如果compar不为空,则最终输出结果还要调用qsort来对数组进行排序后再输出。
从scandir的演示代码,我们可以推算出namelist是一个指向一维指针数组的指针。(一维指针数组等同于 struct dirent ** namelist,这里写在三级指针是因为要从函数里改变namelist的值,必须再多做一级)原因可以参考我的函数传值类型的说明。
以下是一个简单扫描 /usr/lib,并且把所有以lib打头的文件扫描到namelist数组的测试程序,这是参考scandir 提供的样例来修改, alphasort是做原始的ASCII码值比较进行排序的
可以看到namelist是完全动态分配的,不仅数组本身是动态分配,而且数组项指向的空间也是动态分配的。

#include <sys/types.h>
#include <dirent.h>

#include <sys/stat.h>
#include <unistd.h>

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

//扫描所有的lib打头的文件

 int filter_fn(const struct dirent * ent)
 {
   if(ent->d_type != DT_REG)
     return 0;
     
   return (strncmp(ent->d_name,"lib",3) == 0);
 }


void scan_lib(char * dir_name)
{
  int n;
   struct dirent **namelist; // struct dirent * namelist[];

   n = scandir(dir_name, &namelist, filter_fn, alphasort);
   if (< 0)
        perror("scandir");
   else {
               while(n--) {
                   printf("%s\n", namelist[n]->d_name);
                   free(namelist[n]);
               }
               free(namelist);
           }
}

int main(int argc ,char * argv[])
{
   scan_lib("/usr/lib"); 
}


从这个样例,我们可以推算出namelist 的数据结构是.另外一个难点是,这个数组是动态形成的。即根据扫描结果来生成数组。这样在函数里构造这样数据结构还是相当有难度。

最后正式程序如下。完全的源码及测试程序参见附件。

/* 
 * Author : Andrew Huang <bluedrum@163.com>
 *
*/

#define MAX_DIR_ENT 1024

typedef int(*qsort_compar)(const void *, const void *);

int hxy_scandir(const char *dir, struct dirent ***namelist,
              int(*filter)(const struct dirent *),
              int(*compar)(const struct dirent **, const struct dirent **))
{
  DIR * od;
  int n = 0;
  struct dirent ** list = NULL;
  struct dirent * ent ,* p;
  
  if((dir == NULL) || (namelist == NULL))
    return -1;
    
  od = opendir(dir);
  if(od == NULL)
    return -1;
    
   /* 分配一个最大数组 */
  list = (struct dirent **)malloc(MAX_DIR_ENT*sizeof(struct dirent *));
  
  
   while(( ent = readdir(od)) != NULL)
    {
       if( filter && !filter(ent))
          continue;
          
        
          p = (struct dirent *)malloc(sizeof(struct dirent));
          
          memcpy((void *)p,(void *)ent,sizeof(struct dirent));
          list[n] = p;
          
          n++;
          if(>= MAX_DIR_ENT)
            break;
       
    } 
       
    closedir(od); 
   
    /* 改变返回数组大小*/
    *namelist = realloc((void *)list,n*sizeof(struct dirent *));
     if(*namelist == NULL)
        *namelist = list;
  

    /* 数组排序*/ 
    if(compar)
       qsort((void *)*namelist,n,sizeof(struct dirent *),(qsort_compar)compar); 
     
    return n; 
   
}

 

文件:hxy_scandir.zip
大小:1KB
下载:下载

程序分析

1.这一个程序的第一个难点是 namelist个数不确定的.是根据扫描目录的结果来确定,并且通过返回值告诉调用者.一种办法是做两次循环,先扫描一次readdir从头读一次,确定个数,然后再重新读一次读入内容,这样结果是准确了,但是效率极低.另外一种方法读入时采用是使用链表缓存,然后最后一次性存入数组.这样代码过于复杂了.

  最后采用一个折中的办法,即开始一次性分配最大值(1024)的数组,在读入时直接对数组操作.这样代码处理简单,绝大部分情况能正确运行.万一有超过1024,一种是简单丢弃多余,二是扩大最大值.这个方法是在效率和正确性采用一个折衷。

 

2.最后输出时,可以用realloc调整namelist大小再输出,这样可以节约堆空间。

3.关于最后的数组的排序,scandir文档明确告之是采用qsort进行排序,因此最后需要进行这一步,关键是参数怎么填写。

4.这个函数内部的指针操作相当复杂,象三级指针namelist最好不要直接使用,而是要在函数用一个中间指针变量struct dirent ** list 来简化。而且在函数是直接将其作为数组

转自 http://blog.chinaunix.net/uid-9162199-id-108513.html

http://chatgpt.dhexx.cn/article/Q7MTwPU7.shtml

相关文章

5G物联网设备,防止黑客入侵是首要问题

5G IoT设备预计2023年将达到4900万台&#xff0c;研究人员启动了一些程序来防止IoT成为渗透的黑洞。开放标准被认为可以推动物联网设备的互操作性&#xff0c;从而使网络安全软件可以在整个网络中查询设备。许多供应商甚至希望在物联网节点中安装应用程序或代理。毕竟所有移动设…

5G技术在物联网行业的应用

2015年6月&#xff0c;国际电信联盟无线通信部门&#xff08;ITU-R&#xff09;5G 工作组第 22 次会议召开&#xff0c;正式将 5G 命名为 IMT-2020。 什么是5G 5G网络即第五代移动通信网络&#xff0c;数据传输速率远高于以前的蜂窝网络&#xff0c;最高可达10 Gbit/s&#xff…

当5G物联网“遇上”供水?供水行业智慧化更进一步!

伴随着5G、物联网等技术的发展&#xff0c;智慧水务产品数字化和智能化程度正在以前所未有的速度提升。在众多水务应用场景中&#xff0c;二次供水因其居民用水“最后一公里”的特殊性&#xff0c;成为水务智慧化的首选方向。 近期&#xff0c;天翼物联携手水务行业龙头企业上海…

5G 及其对物联网的影响

文章转载自网络通信频道 毫不奇怪&#xff0c;数字世界正在通过先进的解决方案逐渐扩展其功能。物联网不再是一项新技术&#xff0c;而是从制造业到教育等不同行业数字化转型战略的共同组成部分。 5G 连接目前使其在技术世界中的存在更加稳定。根据 2022 年 GSMA 的移动经济报告…

MQTT网关 5G物联网网关 PLC控制工业网关

MQTT网关&#xff0c;两个以上的节点之间通信的新型网关&#xff0c;网络节点之间通过互连来实现双向通信。支持PLC协议转MQTT&#xff0c;实现plc数据采集上云&#xff0c;物联网云平台对接&#xff0c;广泛应用于工业自动化plc远程监测控制。 计讯物联5G MQTT物联网网关TG463…

智慧工厂自动化智能制造对5G物联网技术应用的功能与优势

5G物联网网关应用下的5G智慧工厂自动化智能制造&#xff0c;依托物联网、感知、 无线、大数据云计算等高新技术&#xff0c;连接工厂各节点设备网络&#xff0c;建立数据涌道&#xff0c;实现采集现场生产信息远程在线实时监控&#xff0c;生产过程的全方位可视化和现场生产设备…

【通信】基于粒子群实现5G物联网云网络优化附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

计讯物联5G物联网智能网关助力充电桩运维管理更加高效

随着中国“碳达峰、碳中和”发展目标的提出&#xff0c;新能源汽车渗透率的不断提升&#xff0c;充电桩基础设施建设也随之全面提速。计讯物联聚焦国家政策热点&#xff0c;洞悉行业最新风向&#xff0c;将充电桩、智能电网与物联网技术有机融合&#xff0c;自主研发5G物联网智…

计算机技术5G,计算机学院召开5G与5G物联网专场讲座

原标题&#xff1a;计算机学院召开5G与5G物联网专场讲座 为增强计算机科学与技术专业学子的专业认知&#xff0c;拓展专业视野&#xff0c;增强对5G新技术及5G物联网的了解&#xff0c;11月19日下午&#xff0c;计算机学院计算机科学与技术教研室吴方老师为18级计算机科学与技术…

5G商用的赋能应用阐述,5G物联网应用案例

在5G商用近两年&#xff0c;我们选择深入产业链&#xff0c;对重点行业的企业进行了深入的采访&#xff0c;撰写了一系列关于5G应用案例的文章&#xff0c;让你真正感受到5G是什么&#xff0c;最终制作成行业经典案例集。用微信和远在大洋彼岸的朋友视频通话&#xff0c;视频清…

华为名师拆书直播 | 5G物联网及NB-IoT技术详解

拆书直播是ICT学堂物联网学院全新的直播栏目&#xff0c;老师会从热门优质的物联网技术书籍中挑选&#xff0c;进行拆解学习&#xff0c;并在书籍本身的章节内容上&#xff0c;优化课程设计&#xff0c;外延知识。通过直播讲解的形式把书籍中的精华知识分享给大家。 非常建议平…

5G物联网如何推动边缘计算

低延迟是一项大业务。根据今年早些时候发布的数据&#xff0c;由 5G 连接支持的强大物联网技术配对有望快速增长。据美联社报道&#xff0c; 5G 物联网市场将以每年超过 50% 的速度增长&#xff0c;到 2025 年将占据 62.85 亿美元的市场份额。对于一个明年有望突破 7 亿美元的行…

5G物联网数据网关助力工业企业转型升级

随着工业向智能化、网络化、数字化发展&#xff0c;工业企业的转型升级势在必行。而计讯物联5G物联网数据网关TG463的功能设计足以为先进工业企业实现数据互联共享与精准分析&#xff0c;塑造基于数据驱动的业务模式、管理模式和商业模式&#xff0c;实现多业务系统协同和全系统…

广和通入选中国移动5G物联网开放实验室首批优选产品名录

近期&#xff0c;中国移动5G物联网开放实验室正式发布了5GtoB终端网络兼容性试验规范&#xff0c;并上架开放实验室优选产品名录&#xff0c;加速推动5G终端产品上市商用。广和通5G模组FM650-CN凭借卓越的5GtoB性能&#xff0c;入选首批10款终端优选产品名录。 中国移动5G物联网…

利尔达入驻中国联通5G物联网OpenLab,开启合作新篇章

9月8日&#xff0c;中国联通携手中国信通院承办的“走进联通物联网”生态交流活动在南京举行。作为中国联通在5G物联网产业的长期合作伙伴&#xff0c;利尔达受邀参与本次活动并正式成为中国联通5G物联网OpenLab开放实验室生态伙伴&#xff0c;并被授予5G行业终端模组生态测评证…

5G物联网发展趋势下移动物联网卡面临的4大挑战难点

伴随新一轮科技改革大爆发,社会正式迎来5G物联网时代,通过5G技术与物联网技术相结合成为建设未来智慧城市的新曙光与新手段。在蓬勃发展的5G物联网产业链中,最值得一提的就是移动物联网卡,移动物联网卡是中国移动响应物联网发展潮流,面向企业发展而来的一种战略流量卡,其…

5G物联网网关智能物流无人车互联互通

随着5G物联网高速发展&#xff0c;AGV无人物流车、无人配送车、无人售货车等智能产品应运而生&#xff0c;其科技设计、智能化管控、数字化运营大大提升工作效率&#xff0c;降低人工成本&#xff0c;减小劳动强度&#xff0c;5G物联网网关组网下的智能物流无人车&#xff0c;打…

工业级5G物联网路由器

工业级5G物联网路由器TG463&#xff0c;功能完备&#xff0c;网络构建、数据采集、加密传输、PLC控制、物联网平台对接、云管理&#xff0c;可用于物联网各行业应用&#xff0c;打造便捷经济的数字物联网络。 工业级5G物联网路由器功能 1、模拟量/数字量/开关量等数据采集控制…

为什么5G物联网现在还与你无关

来源&#xff5c;X科技实验室 文&#xff5c;X科技实验室 5G时代除了手机网速变快&#xff0c;被提到最多的是物联网。 然而&#xff0c;就算你已经用上了5G手机&#xff0c;可离5G物联网的距离却依旧很远。 物联网&#xff0c;指的是让所有物品连接在网络中&#xff0c;相互分…

5G中的物联网技术与未来演进方向,路在何方?

导语 | 如果说5G以前是互联网时代&#xff0c;是把人作为连接和服务对象&#xff1b;那么5G之后就是物联网世界&#xff0c;5G将进一步实现物与物、物与人更加多元化的连接&#xff0c;也就是万物智联。我们都知道5G赋予物联网低延迟、高速率、多终端的交互能力&#xff0c;那么…