#include < stdio.h > #include < stdlib.h > #include < string .h > #include < assert.h > #include < limits.h > #include < time.h > #define SUCCEEDED 0 #define FAILED 1 typedef unsigned int UINT;typedef unsigned char UCHAR;typedef unsigned short USHORT; #define UINT_SIZE sizeof(UINT) #define UCHAR_SIZE sizeof(UCHAR) #define USHORT_SIZE sizeof(USHORT) #define CODE_SIZE 256 #define ZIP_HEAD_FLAG 0xaaaaaaaa /* 10间隔 作为文件头 */ struct _HuffmanTreeNode ... { UINT freq; /**//* 频度 */ UCHAR data; struct _HuffmanTreeNode *leftChild; struct _HuffmanTreeNode *rightChild;} ; struct _DataCode ... { USHORT len; UCHAR *pCode;} ; struct _Code2Data ... { USHORT len; UCHAR *pCode; UCHAR data;} ;typedef struct _HuffmanTreeNode HuffmanTreeNode;typedef struct _DataCode DataCode;typedef struct _Code2Data Code2Data;UCHAR ConvertToCodeData( const UCHAR codeStr[CHAR_BIT]); void ConvertToCodeStr(UCHAR codeData, UCHAR codeStr[CHAR_BIT]); /**/ /************************************************************************/ /**/ /* Huffman树相关函数 */ /**/ /************************************************************************/ void GetDataFreq(FILE * fp, UINT freqArr[CODE_SIZE]) ... { UCHAR buffer; fseek(fp, 0L, SEEK_SET); /**//* 将文件指针重新定位到起始位置 */ memset(freqArr, 0, UINT_SIZE * CODE_SIZE); while(!feof(fp)) ...{ fread(&buffer, UCHAR_SIZE, 1, fp); ++freqArr[buffer]; }} void SwapVoidPnt( void ** vpnt1, void ** vpnt2) ... { void *tempPnt = *vpnt1; *vpnt1 = *vpnt2; *vpnt2 = tempPnt;} void BuildHuffmanTree(HuffmanTreeNode ** pTreeHead, const UINT freqArr[CODE_SIZE]) ... { HuffmanTreeNode **dataFreqArr; HuffmanTreeNode *tempInsertTreeNode; UINT freqLen = CODE_SIZE; int i; dataFreqArr = (HuffmanTreeNode **)malloc(sizeof(HuffmanTreeNode*) * freqLen); for(i = 0; i < CODE_SIZE; ++i) ...{ dataFreqArr[i] = (HuffmanTreeNode *)malloc(sizeof(HuffmanTreeNode)); dataFreqArr[i]->data = (UCHAR)i; dataFreqArr[i]->freq = freqArr[i]; dataFreqArr[i]->leftChild = NULL; dataFreqArr[i]->rightChild = NULL; } while(freqLen != 1) ...{ /**//* 把频度最小的两个移到最后两位 并且最后的小于最后第二个 */ if(dataFreqArr[freqLen-1]->freq > dataFreqArr[freqLen-2]->freq) SwapVoidPnt(dataFreqArr + freqLen-1, dataFreqArr + freqLen-2); for(i = freqLen-2-1; i >= 0; --i) ...{ if(dataFreqArr[freqLen-1]->freq > dataFreqArr[i]->freq) ...{ SwapVoidPnt(dataFreqArr + freqLen-2, dataFreqArr + i); SwapVoidPnt(dataFreqArr + freqLen-1, dataFreqArr + freqLen-2); } else if(dataFreqArr[freqLen-2]->freq > dataFreqArr[i]->freq) ...{ SwapVoidPnt(dataFreqArr + freqLen-2, dataFreqArr + i); } } /**//* 合并最后两个 */ tempInsertTreeNode = (HuffmanTreeNode *)malloc(sizeof(HuffmanTreeNode)); tempInsertTreeNode->freq = dataFreqArr[freqLen-1]->freq + dataFreqArr[freqLen-2]->freq; tempInsertTreeNode->leftChild = dataFreqArr[freqLen-1]; tempInsertTreeNode->rightChild = dataFreqArr[freqLen-2]; dataFreqArr[freqLen-2] = tempInsertTreeNode; --freqLen; } *pTreeHead = dataFreqArr[0]; free(dataFreqArr); /**//* 只是存放节点用的 离开之前应释放 */} int CmpCode2Data( const void * op1, const void * op2) ... { UINT minLen = ((DataCode*)op1)->len < ((DataCode*)op2)->len ? ((DataCode*)op1)->len : ((DataCode*)op2)->len; UINT i; for(i = 0; i < minLen; ++i) ...{ if(((DataCode*)op1)->pCode[i] != ((DataCode*)op2)->pCode[i]) return ((DataCode*)op1)->pCode[i] - ((DataCode*)op2)->pCode[i]; } if(((DataCode*)op1)->len == ((DataCode*)op2)->len) return 0; if(((DataCode*)op1)->len < ((DataCode*)op2)->len) return -((DataCode*)op2)->pCode[i]; return ((DataCode*)op1)->pCode[i];} void RebuildHuffmanTreeOrder(HuffmanTreeNode ** pTreeHead, UINT start, UINT end, UINT deep, const Code2Data code2DataArr[CODE_SIZE]) ... { UINT mid, i; HuffmanTreeNode *insertChild = NULL; assert(start < end); assert(deep < CODE_SIZE); /**//* 根据当前层是0还是1 把数组分成两部分 */ mid = end; for(i = start; i < end; ++i) ...{ assert(code2DataArr[i].len > deep); if(code2DataArr[i].pCode[deep] != 0) ...{ mid = i; break; } } if(*pTreeHead == NULL) ...{ *pTreeHead = (HuffmanTreeNode *)malloc(sizeof(HuffmanTreeNode)); //assert(*pTreeHead); (*pTreeHead)->leftChild = NULL; (*pTreeHead)->rightChild = NULL; } /**//* 不能在这里插数据 即使只有一个 也不能将其作为头节点 必须通过头节点连至他 他也是有编码的 就是0 */ /**//*if(start == end-1) { (*pTreeHead)->leftChild = NULL; (*pTreeHead)->rightChild = NULL; (*pTreeHead)->data = code2DataArr[start].data; return ; }*/ /**//* 当前层是0的部分 */ if(mid-1 == start) ...{ insertChild = (HuffmanTreeNode *)malloc(sizeof(HuffmanTreeNode)); insertChild->leftChild = NULL; insertChild->rightChild = NULL; insertChild->data = code2DataArr[mid - 1].data; (*pTreeHead)->leftChild = insertChild; } else RebuildHuffmanTreeOrder(&(*pTreeHead)->leftChild, start, mid, deep+1, code2DataArr); /**//* 当前层是1的部分 */ if(mid == end-1) ...{ insertChild = (HuffmanTreeNode *)malloc(sizeof(HuffmanTreeNode)); insertChild->leftChild = NULL; insertChild->rightChild = NULL; insertChild->data = code2DataArr[mid].data; (*pTreeHead)->rightChild = insertChild; }else RebuildHuffmanTreeOrder(&(*pTreeHead)->rightChild, mid, end, deep+1, code2DataArr);} void RebuildHuffmanTree(HuffmanTreeNode ** pTreeHead, const DataCode dataCodeArr[CODE_SIZE]) ... { Code2Data code2DataArr[CODE_SIZE]; UINT i; for(i = 0; i < CODE_SIZE; ++i) ...{ code2DataArr[i].data = i; code2DataArr[i].len = dataCodeArr[i].len; code2DataArr[i].pCode = dataCodeArr[i].pCode; } qsort(code2DataArr, CODE_SIZE, sizeof(Code2Data), CmpCode2Data); RebuildHuffmanTreeOrder(pTreeHead, 0, CODE_SIZE, 0, code2DataArr); /**//* 不对code2DataArr中的指针进行释放 因为code2DataArr中的指针是来自dataCodeArr中的 */} void DeleteHuffmanTree(HuffmanTreeNode ** pTreeHead) ... { if(*pTreeHead != NULL) ...{ if((*pTreeHead)->leftChild != NULL) DeleteHuffmanTree(&((*pTreeHead)->leftChild)); if((*pTreeHead)->rightChild != NULL) DeleteHuffmanTree(&((*pTreeHead)->rightChild)); free(*pTreeHead); *pTreeHead = NULL; }} void GetHuffmanCode( const HuffmanTreeNode * pTreeHead, UCHAR code[CODE_SIZE], USHORT codeLen, DataCode dataCodeArr[CODE_SIZE]) ... { if(pTreeHead != NULL) ...{ if(pTreeHead->leftChild != NULL) ...{ code[codeLen] = 0; GetHuffmanCode(pTreeHead->leftChild, code, codeLen+1, dataCodeArr); assert(pTreeHead->rightChild != NULL); /**//* 不可能出现一边有孩子节点 一边又没有的情况 */ code[codeLen] = 1; GetHuffmanCode(pTreeHead->rightChild, code, codeLen+1, dataCodeArr); } else ...{ /**//* 叶子节点 */ dataCodeArr[pTreeHead->data].pCode = (UCHAR *)malloc(UCHAR_SIZE * codeLen); memcpy(dataCodeArr[pTreeHead->data].pCode, code, UCHAR_SIZE * codeLen); dataCodeArr[pTreeHead->data].len = codeLen; } }} void GetFileHuffmanCode(FILE * fp, DataCode dataCodeArr[CODE_SIZE]) ... { HuffmanTreeNode *pTreeHead = NULL; UINT freqArr[256]; UCHAR code[CODE_SIZE]; GetDataFreq(fp, freqArr); BuildHuffmanTree(&pTreeHead, freqArr); memset(dataCodeArr, 0, sizeof(DataCode) * CODE_SIZE); memset(code, 0, UCHAR_SIZE * CODE_SIZE); GetHuffmanCode(pTreeHead, code, 0, dataCodeArr); DeleteHuffmanTree(&pTreeHead);} /**/ /************************************************************************/ /**/ /* 压缩 解压缩的相关文件操作函数 */ /**/ /************************************************************************/ /**/ /* 头存的是字符和编码对应的表 存频度 再重新构造huffman树会有问题 因为有可能存在频度相同的 */ int ReadZipFileHead(FILE * fp, DataCode dataCodeArr[CODE_SIZE]) ... { UINT zipHeadFlag; USHORT codeLen, i, j; UCHAR codeBuffer, data; UCHAR codeStr[CHAR_BIT]; fseek(fp, 0L, SEEK_SET); fread(&zipHeadFlag, UINT_SIZE, 1, fp); if(zipHeadFlag != ZIP_HEAD_FLAG) return FAILED; memset(dataCodeArr, 0, sizeof(DataCode) * CODE_SIZE); for(i = 0; i < CODE_SIZE; ++i) ...{ fread(&data, UCHAR_SIZE, 1, fp); assert(data == i); fread(&codeLen, USHORT_SIZE, 1, fp); dataCodeArr[data].len = codeLen; /**//* 把编码还原成字符串 */ assert(dataCodeArr[data].pCode == NULL); dataCodeArr[data].pCode = (UCHAR *)malloc(UCHAR_SIZE * codeLen); for(j = 0; j < codeLen - codeLen % CHAR_BIT; j += CHAR_BIT) ...{ fread(&codeBuffer, UCHAR_SIZE, 1, fp); ConvertToCodeStr(codeBuffer, codeStr); memcpy(dataCodeArr[data].pCode + j, codeStr, UCHAR_SIZE * CHAR_BIT); } if(codeLen % CHAR_BIT != 0) ...{ fread(&codeBuffer, UCHAR_SIZE, 1, fp); ConvertToCodeStr(codeBuffer, codeStr); memcpy(dataCodeArr[data].pCode + j, codeStr, UCHAR_SIZE * (codeLen % CHAR_BIT)); } } return SUCCEEDED;} void WriteZipFileHead(FILE * fp, const DataCode dataCodeArr[CODE_SIZE]) ... { USHORT i, j; UCHAR codeBuffer, codeStr[CHAR_BIT]; UINT zipHeadFlag = ZIP_HEAD_FLAG; fseek(fp, 0L, SEEK_SET); fwrite(&zipHeadFlag, UINT_SIZE, 1, fp); for(i = 0; i < CODE_SIZE; ++i) ...{ fwrite(&i, UCHAR_SIZE, 1, fp); fwrite(&dataCodeArr[i].len, USHORT_SIZE, 1, fp); /**//* 将编码字符串合成字节码写入 */ for(j = 0; j < dataCodeArr[i].len - dataCodeArr[i].len % CHAR_BIT; j += CHAR_BIT) ...{ memcpy(codeStr, dataCodeArr[i].pCode + j, UCHAR_SIZE * CHAR_BIT); codeBuffer = ConvertToCodeData(codeStr); fwrite(&codeBuffer, UCHAR_SIZE, 1, fp); } if(dataCodeArr[i].len % CHAR_BIT != 0) ...{ memcpy(codeStr, dataCodeArr[i].pCode + j, UCHAR_SIZE * (dataCodeArr[i].len % CHAR_BIT)); codeBuffer = ConvertToCodeData(codeStr); fwrite(&codeBuffer, UCHAR_SIZE, 1, fp); } }} UCHAR ConvertToCodeData( const UCHAR codeStr[CHAR_BIT]) ... { UCHAR retCode = 0; int i; for(i = CHAR_BIT-1; i >= 0; --i) ...{ retCode <<= 1; if(codeStr[i] != 0) retCode |= 1; } return retCode;} void ConvertToCodeStr(UCHAR codeData, UCHAR codeStr[CHAR_BIT]) ... { UINT i; for(i = 0; i < CHAR_BIT; ++i) ...{ codeStr[i] = ((codeData & 1) != 0); codeData >>= 1; }} int ZipFile( const char * sourceFileName, const char * targetFileName) ... { FILE *sourceFp = NULL, *targetFp = NULL; DataCode dataCodeArr[CODE_SIZE]; USHORT writeCodeLen, i; UCHAR writeCode[CHAR_BIT], readData, writeData, lastBtyeLen; fpos_t lastBtyePos; if((sourceFp = fopen(sourceFileName, "rb")) == NULL) ...{ printf("打开%s文件错误! ", sourceFileName); return FAILED; } if((targetFp = fopen(targetFileName, "w+b")) == NULL) ...{ printf("打开%s文件错误! ", targetFileName); fclose(sourceFp); return FAILED; } GetFileHuffmanCode(sourceFp, dataCodeArr); WriteZipFileHead(targetFp, dataCodeArr); lastBtyeLen = 0; fgetpos(targetFp, &lastBtyePos); /**//* 记录位子 后面得到长度信息后 再在这里写 */ fwrite(&lastBtyeLen, UCHAR_SIZE, 1, targetFp); /**//* 对源数据进行编码转换 并写入目标文件中 */ memset(writeCode, 0, CHAR_BIT); writeCodeLen = 0; fseek(sourceFp, 0L, SEEK_SET); while(!feof(sourceFp)) ...{ fread(&readData, UCHAR_SIZE, 1, sourceFp); for(i = 0; i < dataCodeArr[readData].len; ++i) ...{ writeCode[writeCodeLen++] = dataCodeArr[readData].pCode[i]; if(writeCodeLen >= CHAR_BIT) ...{ writeData = ConvertToCodeData(writeCode); fwrite(&writeData, UCHAR_SIZE, 1, targetFp); memset(writeCode, 0, UCHAR_SIZE * CHAR_BIT); writeCodeLen = 0; } } } /**//* 把剩余的写入文件 */ if(writeCodeLen != 0) ...{ writeData = ConvertToCodeData(writeCode); fwrite(&writeData, UCHAR_SIZE, 1, targetFp); } lastBtyeLen = writeCodeLen; fsetpos(targetFp, &lastBtyePos); fwrite(&lastBtyeLen, UCHAR_SIZE, 1, targetFp); /**//* 清理 */ for(i = 0; i < CODE_SIZE; ++i) ...{ if(dataCodeArr[i].pCode != NULL) ...{ free(dataCodeArr[i].pCode); dataCodeArr[i].pCode = NULL; } } fclose(sourceFp); fclose(targetFp); return SUCCEEDED;} int UnzipFile( const char * sourceFileName, const char * targetFileName) ... { FILE *sourceFp = NULL, *targetFp = NULL; DataCode dataCodeArr[CODE_SIZE]; HuffmanTreeNode *pTreeHead = NULL, *pTreeNode = NULL; UCHAR codeStream[CODE_SIZE], codeStr[CHAR_BIT], readData, writeData, lastBtyeLen; int codeStreamLen, i; if((sourceFp = fopen(sourceFileName, "rb")) == NULL) ...{ printf("打开%s文件错误! ", sourceFileName); return FAILED; } if((targetFp = fopen(targetFileName, "w+b")) == NULL) ...{ printf("打开%s文件错误! ", targetFileName); fclose(sourceFp); return FAILED; } ReadZipFileHead(sourceFp, dataCodeArr); fread(&lastBtyeLen,UCHAR_SIZE, 1, sourceFp); RebuildHuffmanTree(&pTreeHead, dataCodeArr); codeStreamLen = 0; while(!feof(sourceFp) || codeStreamLen > 0) ...{ while(!feof(sourceFp) && codeStreamLen < CODE_SIZE - CHAR_BIT) ...{ fread(&readData, UCHAR_SIZE, 1, sourceFp); ConvertToCodeStr(readData, codeStr); memcpy(codeStream+codeStreamLen, codeStr, CHAR_BIT); codeStreamLen += CHAR_BIT; if(feof(sourceFp)) codeStreamLen -= lastBtyeLen + CHAR_BIT; /**//* 咋就多出一字节 纳闷 */ } /**//* 通过编码查找原数据 */ pTreeNode = pTreeHead; for(i = 0; i < codeStreamLen; ++i) ...{ if(codeStream[i] == 0) ...{ pTreeNode = pTreeNode->leftChild; if(pTreeNode->leftChild == NULL) break; } else ...{ pTreeNode = pTreeNode->rightChild; if(pTreeNode->leftChild == NULL) break; } } assert(pTreeNode->rightChild == NULL); /**//* 是一个数据节点 左右子节点肯定都为空 */ writeData = pTreeNode->data; fwrite(&writeData, UCHAR_SIZE, 1, targetFp); /**//* 把读取过的去掉 */ codeStreamLen -= i + 1; memcpy(codeStream, codeStream+i+1, codeStreamLen); } /**//* 清理 */ DeleteHuffmanTree(&pTreeHead); for(i = 0; i < CODE_SIZE; ++i) ...{ if(dataCodeArr[i].pCode != NULL) ...{ free(dataCodeArr[i].pCode); dataCodeArr[i].pCode = NULL; } } fclose(sourceFp); fclose(targetFp); return SUCCEEDED;} /**/ /************************************************************************/ /**/ /* 测试代码 */ /**/ /************************************************************************/ void TestCreateTestFile( const char * fileName) ... { FILE *fp = NULL; UINT i; if((fp = fopen(fileName, "w+b")) == NULL) ...{ printf("打开%s文件失败! ", fileName); return ; } for(i = 0; i < 45; ++i) fputc('a', fp); for(i = 0; i < 13; ++i) fputc('b', fp); for(i = 0; i < 12; ++i) fputc('c', fp); for(i = 0; i < 16; ++i) fputc('d', fp); for(i = 0; i < 9; ++i) fputc('e', fp); for(i = 0; i < 5; ++i) fputc('f', fp); fclose(fp);} void Test_GetDataFreq( void ) ... { UINT freqArr[CODE_SIZE]; FILE *fp = NULL; fp = fopen("Test.txt", "rb"); assert(fp != NULL); GetDataFreq(fp, freqArr); assert(freqArr['a'] = 45); assert(freqArr['b'] = 13); assert(freqArr['c'] = 12); assert(freqArr['d'] = 16); assert(freqArr['e'] = 9); assert(freqArr['f'] = 5); fclose(fp);} void Test_BuildHuffmanTree( void ) ... { UINT freqArr[CODE_SIZE]; HuffmanTreeNode *pTreeHead = NULL, *pTreeNode = NULL; /**//*memset(freqArr, 0, UINT_SIZE * CODE_SIZE); freqArr['a'] = 45; freqArr['b'] = 13; freqArr['c'] = 12; freqArr['d'] = 16; freqArr['e'] = 9; freqArr['f'] = 5;*/ FILE *fp = NULL; fp = fopen("Test.txt", "rb"); assert(fp != NULL); GetDataFreq(fp, freqArr); fclose(fp); BuildHuffmanTree(&pTreeHead, freqArr); pTreeNode = pTreeHead; assert(pTreeNode->leftChild->data == 'a'); pTreeNode = pTreeNode->rightChild; assert(pTreeNode->leftChild->leftChild->data == 'c'); assert(pTreeNode->leftChild->rightChild->data == 'b'); pTreeNode = pTreeNode->rightChild; assert(pTreeNode->rightChild->data == 'd'); pTreeNode = pTreeNode->leftChild; assert(pTreeNode->leftChild->rightChild->data == 'f'); assert(pTreeNode->rightChild->data == 'e'); DeleteHuffmanTree(&pTreeHead);} void TestNormalStr2CodeStr( const char * normalStr, UCHAR codeStr[CODE_SIZE], USHORT * codeLen) ... { USHORT i; *codeLen = (USHORT)strlen(normalStr); for(i = 0; i < *codeLen; ++i) codeStr[i] = (normalStr[i] == '1');} void Test_GetFileHuffmanCode( void ) ... { DataCode dataCodeArr[CODE_SIZE]; FILE *fp = NULL; UCHAR codeStr[CODE_SIZE]; USHORT codeLen, i; fp = fopen("Test.txt", "rb"); assert(fp != NULL); GetFileHuffmanCode(fp, dataCodeArr); fclose(fp); TestNormalStr2CodeStr("0", codeStr, &codeLen); assert(memcmp(dataCodeArr['a'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0); TestNormalStr2CodeStr("101", codeStr, &codeLen); assert(memcmp(dataCodeArr['b'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0); TestNormalStr2CodeStr("100", codeStr, &codeLen); assert(memcmp(dataCodeArr['c'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0); TestNormalStr2CodeStr("111", codeStr, &codeLen); assert(memcmp(dataCodeArr['d'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0); TestNormalStr2CodeStr("1101", codeStr, &codeLen); assert(memcmp(dataCodeArr['e'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0); TestNormalStr2CodeStr("11001", codeStr, &codeLen); assert(memcmp(dataCodeArr['f'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0); for(i = 0; i < CODE_SIZE; ++i) ...{ if(dataCodeArr[i].pCode != NULL) ...{ free(dataCodeArr[i].pCode); dataCodeArr[i].pCode = NULL; } }} void Test_ReadWriteZipFileHead( void ) ... { DataCode dataCodeArr[CODE_SIZE]; FILE *fp = NULL; UCHAR codeStr[CODE_SIZE]; USHORT codeLen, i; fp = fopen("Test.txt", "rb"); assert(fp != NULL); GetFileHuffmanCode(fp, dataCodeArr); fclose(fp); fp = fopen("Test_ZipFileHead.txt", "w+b"); assert(fp != NULL); WriteZipFileHead(fp, dataCodeArr); for(i = 0; i < CODE_SIZE; ++i) ...{ if(dataCodeArr[i].pCode != NULL) ...{ free(dataCodeArr[i].pCode); dataCodeArr[i].pCode = NULL; } } memset(dataCodeArr, 0, sizeof(DataCode) * CODE_SIZE); fseek(fp, 0L, SEEK_SET); assert(fp != NULL); ReadZipFileHead(fp, dataCodeArr); fclose(fp); TestNormalStr2CodeStr("0", codeStr, &codeLen); assert(memcmp(dataCodeArr['a'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0); TestNormalStr2CodeStr("101", codeStr, &codeLen); assert(memcmp(dataCodeArr['b'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0); TestNormalStr2CodeStr("100", codeStr, &codeLen); assert(memcmp(dataCodeArr['c'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0); TestNormalStr2CodeStr("111", codeStr, &codeLen); assert(memcmp(dataCodeArr['d'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0); TestNormalStr2CodeStr("1101", codeStr, &codeLen); assert(memcmp(dataCodeArr['e'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0); TestNormalStr2CodeStr("11001", codeStr, &codeLen); assert(memcmp(dataCodeArr['f'].pCode, codeStr, codeLen * UCHAR_SIZE) == 0); for(i = 0; i < CODE_SIZE; ++i) ...{ if(dataCodeArr[i].pCode != NULL) ...{ free(dataCodeArr[i].pCode); dataCodeArr[i].pCode = NULL; } }} /**/ /*int main(void){ TestCreateTestFile("Test.txt"); Test_GetDataFreq(); Test_BuildHuffmanTree(); Test_GetFileHuffmanCode(); Test_ReadWriteZipFileHead(); return 0;}*/ /**/ /************************************************************************/ /**/ /* 主程序函数 */ /**/ /************************************************************************/ int main( void ) ... { char *fileName = "Test.txt"; char *zipFileName = "ZipTest.txt"; char *unzipFileName = "UnzipTest.txt"; ZipFile(fileName, zipFileName); UnzipFile(zipFileName, unzipFileName); return 0;}