yolo是c语言写的,并且读取图像数据是根据txt文件读取的,这次主要记录一下
list *plist = get_paths(train_images); //int N = plist->size; char **paths = (char **)list_to_array(plist);
主要介绍这两个函数的由来以及相关介绍.里面有的解释不清楚以及出错的地方欢迎指正.
#include <stdio.h> #include <stdlib.h> #include <stdlib.h> #include <string.h> #include <malloc.h> #include <stddef.h> typedef struct node{ void *val;//指针,目的是指向每一行的头一个指针位置,用来存字符串的,*val指的是字符串的首地址 struct node *next;//这边可以理解成一个链表,*next指向链表的下一端 struct node *prev;//*prev指向链表的上一端 } node; typedef struct list{ int size; //这边是指图片的数量, node *front;//可以理解成最简单的二叉树,深度为2,只有front和back两个孩子,front里面又是一个node结构体,我们可以看node结构体 node *back; } list; void **list_to_array(list *l) { void **a = calloc(l->size, sizeof(void*)); int count = 0; node *n = l->front;/*结构体,指针地址指向l->front,此时的n就是l->front里面的内容*/ // node *n = l->back;/*这边我不怎么想得通,为什么是front,而不是back.我认为了l->back才是这个数据结构 //当然,我的想法是错的,只是没看懂这个数据结构*/ while(n){ a[count++] = n->val;//这个while循环就是将链表n中的所有字符串赋值给a[] n = n->next;//继续链表n的下一个 } return a; } list *make_list() { list *l = malloc(sizeof(list));//在c语言中结构体不可以再定义结构体变量,但是可以定义结构体指针 //在c语言中,指针如果不开辟空间,是不能直接使用的 // fprintf(stderr,"%d\n",sizeof(list));//返回的是24,也就是为指针l开辟一个24的空间,关于sizeof求嵌套结构体的大小 //有空会简单介绍一下 l->size = 0; l->front = 0; l->back = 0; return l; } char *fgetl(FILE *fp) { if(feof(fp)) return 0;//int型,检查文件是否结束,如果结束,返回0 size_t size = 512; char *line = malloc(size*sizeof(char));//开辟一个512的空间,如果图像路径超过512个字符,会出问题的,当然,谁的路径会有这么长呢? if(!fgets(line, size, fp)){/*从文件流读取一行送到缓冲区,每行的字符不能超过size-1. 当遇到换行符或者缓冲区已满,fgets就会停止,返回读到的数据*/ free(line);//free的时候,系统会比对一下这个地址,是不是malloc申请的,如果不是,不给释放 //如果是的话,系统就知道要释放多大内存,因为malloc的时候,系统有记录的。 return 0; } } void list_insert(list *l, void *val) { node *new = malloc(sizeof(node));//为新的new开辟空间,注意这个new永远都是新的 new->val = val;//将参数val的内容赋值给new里面的val,其实这是将每一行的图像路径字符串给了val new->next = 0;//new的下一个为0,但是前面一个还是起作用的 if(!l->back){//如果l-back不为空 l->front = new;//l的front孩子 就是new这个node字符串 new->prev = 0;//l的前一个孩子为0 }else{//这边没怎么看懂数据结构的目的,只能浅谈一下,希望有了解的道友交流一波 l->back->next = new;//l的back孩子的下一个为new new->prev = l->back;//new链表的前一个为l的back孩子,new是链表 /*链表,给了这个表的下一个值,那也要给上一个值啊,准确的说,这个是构建l->back链表,l->back的下一个是new,而这个new的上一个是l->back*/ } l->back = new;//l的back孩子是new ++l->size;//l-size记录有多少行,也就是多少张图像 } void file_error(char *s) { fprintf(stderr, "Couldn't open file: %s\n", s); exit(0); } list *get_paths(char *filename) { char *path; FILE *file = fopen(filename, "r");//打开文件,文件指针名=fopen(文件名,使用文件方式) //“文件指针名”必须是被说明为FILE 类型的指针变量; if(!file) file_error(filename); list *lines = make_list(); while((path=fgetl(file))){ //这边涉及比较复杂的数据结构,文字很难描述 list_insert(lines, path); } fclose(file); return lines; } int main() { char *train_images = "/home/hjxu/Yolo/hjxu_train_code/2007_train.txt"; // char *copy = malloc(strlen(train_images)+1); // strncpy(copy, train_images, strlen(train_images)+1); // fprintf(stderr,"%s\n",copy); list *plist = get_paths(train_images); // fprintf(stderr, plist->size); char **paths = (char **)list_to_array(plist);//将plist里面的内容转化成数组 int i; for(i=0;i<plist->size;i++) { fprintf(stderr, "%s", *(paths+i));//**paths就是这个数组的,*(paths+i)则是第i行,或者paths[i]就可以了 } return 0; }
有一点我想不通,一直数据都是放在l的back里,为什么会调用l的front,希望小伙伴能help一下