2017.11.7
今天阅读了cantjie的关于哈夫曼编码任务的程序中的header.h, list.c与count.c中的count_from_file函数
有如下认识:
1.首先在header.h中声明项目所需的预编译指令、库函数以及所需的数据结构和函数的声明。
2.在本任务中,需要
(1)定义每个结点的数据类型 listNode,其中有借点数据域单独的结构体 listData.
(2) 因为后续的哈夫曼编码中的建立哈夫曼树等操作都是基于链表的,于是需要一个listHead的数据类型,这种数据类型的head中存储链表的相关信息,包括length(文件中不同字符的数目)、cnt(字符数)、布尔型的duplicate_tag以判断字符是否重复,
而且在判断字符是否重复,以及最终统计文件总字符数的时候需要遍历整个链表,于是得定义一个遍历的标签traverse_tag(也是bool型)
头结点head中应包含head->next,head->curr,head->tail.
(3)基于链表的函数有
listHead*create_list(void) //创建一个新链表,并返回链表头
listHead*append_list(listHead *head,char ch[]) //如果新读入字符原先不存在,则用该函数创建新结点
listHead*foreach(listHead *head) //对链表进行循环,用以检查重复和最后统计频率
listHead *count_from_file(char filename[]) // 函数以统计文件中字符的频率和频数
2017.11.14
今天继续学习,试着写了读取字符的函数count_from_file(char filename[])
#include"header.h"
listHead *count_from_file(char filename[]){
FILE* fp;
listHead* head;
listData* data;
bool duplicate_tag;
char ch[2]; //用两个字节来适应文档中会出现汉字的情况
fp = fopen(filename, 'r');
head = create();
while (*ch = fgetc(fp) != EOF){
if (ch[0] < 0) //ch[0]<0代表该字符为汉字,则再读一位
{
ch[1] = fgetc(fp);
}
else { ch[1] = '\0'; }
duplicate_tag = false;
//判断是否重复
while (data = foreach(head)){ //此处data循环指向链表中的结点,即foreach函数按次序返回链表中的结点的地址
//如果两字符串相等,则频数+1
//不能用strcmp(data->ch,ch)来比较,因为该函数会一直比较直到'\0'
if (0 == memcmp(data->ch, ch, 2))
{
data->cnt++;
duplicate_tag = true;
head->traverseTag = false;
break;
}
//如果该字符还没有出现,则调用append_list函数
}
}
}
}
2017.11.21
今天在写添加结点的函数listNode* append_list(listHead*head, char ch[])时,得到一些启发:
在写函数时,要注意边界条件,如分配空间要判断是否成功,对链表添加结点时判断链表长度状况:长度为零还是其他。
这里写代码片