yolov3源码解析——文件读取方式以及存储引用方式

本文详细分析了源代码中的文件引用方式,通过两个关键结构体node和list,阐述了文件内容如何被引用和组织。同时,深入探讨了fgetl函数的实现,解释了其如何高效读取文件行数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

虽然在上一篇文章中说到了相关内容,但是不够具体,本文我们把这一部分的代码单独分析,更清楚的分析源代码中的文件引用方式。

先引出两个结构体,定义在include/darknet.h中:

typedef struct node{
    void *val;
    struct node *next;
    struct node *prev;
} node;

typedef struct list{
    int size;
    node *front;
    node *back;
} list;

这两个结构体用于文件内容的引用,node是节点,存储的是文件中的一行数据,但是并不是以直接字符串的形式,而是一个指针(void *val)指向数据行的首地址。

node是节点是数据行,是文件的组成元素,文件是由node节点链接而成的,所以node中的*next,*prev分别指后节点索引,前节点索引。其实这样已经链成了文件索引链,但是不利于引用。为了利于引用,用一个新的结构体存储一个文件链的头节点和尾节点,以及节点数(文件中数据行的数量),这就是list

list中size指节点数,*front为首节点,*back为尾节点

所以读取文件时,创建空的list,每读一行数据,创建一个node,并链接入list

这是文件的引用方式,下面说说文件的读取:

fgetl函数定义在src/utils.h中,在src/utils.c中实现,代码如下:

char *fgetl(FILE *fp)
{
    if(feof(fp)) return 0;
    //line的大小为512个char
    size_t size = 512;
    char *line = malloc(size*sizeof(char));
    if(!fgets(line, size, fp)){
        free(line);
        return 0;
    }

    //获取字符串真实大小,不包含null
    size_t curr = strlen(line);

    while((line[curr-1] != '\n') && !feof(fp)){
        if(curr == size-1){
            size *= 2;
            line = realloc(line, size*sizeof(char));
            if(!line) {
                printf("%ld\n", size);
                malloc_error();
            }
        }
        size_t readsize = size-curr;
        if(readsize > INT_MAX) readsize = INT_MAX-1;
        fgets(&line[curr], readsize, fp);
        curr = strlen(line);
    }
    if(line[curr-1] == '\n') line[curr-1] = '\0';

    return line;
}

在用惯了其他高级语言后,这样的算法有点让人头大,fgets按字符读取,设置的读取大小为512,因为,虽然文件行理论可以无限大,但是现在的文本文件以1024为界限,满1024就自动添加换行符,512为1024的一般,可以看但如果512个字符依然没有将文件行读全,就扩大到1024的大小再读,这样做为了减少内存和检索时间。读取数据后,strlen返回真实字符串长度,即不包含末尾的null

通过判断最后一个字符是否是换行符来判度文件行是否全部读入,最后返回的是文件行数据的头指针

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫猫虫(——)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值