#include "string.h"
#include "malloc.h"
#define MOD_ADLER 65521
#define HASHMAX 1000
#define MAX_INT 9999999 // 最大读取数字为99999999
#define CHARBUFLEN 40960
#define DECOMPRESSINITLEN 1024
struct stringInfo
{
int No // 字符串出现的次序
char * str // 字符串
struct stringInfo * next // 下一节点
} * strTable[HASHMAX] // 用于压缩
int isCompress
char ** strTableDe // 解压缩表,用于解压缩
long deTableLen // 解压缩表长度
long curStrNum // 目前的字符串数量
// 程序初始化
void init()
{
int i
curStrNum = 1
isCompress = 1 // 压缩模式,等于0时解压缩
if(isCompress)
{
for(i=0 i<HASHMAX i++) strTable[i] = NULL
deTableLen = 0
strTableDe = NULL
}
else
{
deTableLen = DECOMPRESSINITLEN
strTableDe = (char **)malloc(deTableLen * sizeof(char *))
for(i=0 i<deTableLen i++) strTableDe[i] = NULL
}
}
// 重新申请内存
void ReMallocDeTable()
{
deTableLen <<= 1
strTableDe = (char **)realloc(strTableDe, deTableLen * sizeof(char *))
}
// 程序结束,释放内存
void over()
{
int i
struct stringInfo *pNext, *pDel
for(i=0 i<HASHMAX i++)
{
pNext = strTable[i]
while(pNext)
{
free(pNext->str)
pDel = pNext
pNext = pNext->next
free(pDel)
}
}
if(strTableDe)
{
for(i=0 i<curStrNum i++)
{
//printf("%d\t%s\n", i, strTableDe[i])
free(strTableDe[i])
}
free(strTableDe)
}
}
// adler32 校验和算法
unsigned long adler32(unsigned char * data, size_t len)
{
unsigned long a = 1, b = 0
size_t index
for (index = 0 index < len ++index)
{
a = (a + data[index]) % MOD_ADLER
b = (b + a) % MOD_ADLER
}
return (b << 16) | a
}
// 求字符串的Hash,实现快速查找, 这里用的是adler32算法,可以使用其它任何hash方法
unsigned long Hash(const char * str)
{
return adler32((unsigned char*)str, strlen(str)) % HASHMAX
}
// 复制新字符串
char * copyNewStr(const char * str)
{
char * r = (char *)malloc(strlen(str) + 1)
strcpy(r, str)
return r
}
// 取得字符串出现的次序
int getStrPos(const char * str)
{
unsigned long hash
struct stringInfo * pFirst, * pNext, * pNew
hash = Hash(str)
pNext = pFirst = strTable[hash]
while(pNext)
{
if(strcmp(pNext->str, str) == 0) return pNext->No
pNext = pNext->next
}
// 没有找到匹配的字符串
pNew = (struct stringInfo *)malloc(sizeof(struct stringInfo))
pNew->next = NULL
pNew->No = curStrNum++
pNew->str = copyNewStr(str)
if(pFirst == NULL) strTable[hash] = pNew
else
{
pNext = pFirst
while(pNext->next) pNext = pNext->next
pNext->next = pNew
}
return -1
}
// 读取字符串, 字符串以空格为结束符
// 返回负数的绝对值是读取的是字符串长度,正数为读取的数字
int ReadStr(char * out, const char * in)
{
char *po, *pn
const char *pi
int r
po = out
pi = in
while(('a' <= *pi && *pi <= 'z') || ('A' <= *pi && *pi <= 'Z') || ('0' <= *pi && *pi <= '9'))
*po++ = *pi++ // 只复制大小写字母和数字
*po = 0
// 试着转化为纯数字
r = 0
pn = out
while('0' <= *pn && *pn <= '9')
{
if(r > MAX_INT) break
r *= 10
r += *pn++ - '0'
}
if(*pn) return out - po // 未成功转化为数字
else return (r & 0x7FFFFFF) | (((po - out) & 0xF) << 27)
}
void main()
{
char readFileBuf[CHARBUFLEN], readStrBuf[CHARBUFLEN]
char *prfb
int num
FILE *fpr, *fpw
fpr = fopen("source.txt", "r") // 输入文件
fpw = fopen("object.txt", "w") // 输出文件
if(fpr == NULL || fpw == NULL) return
init()
while(!feof(fpr))
{
if(fgets(readFileBuf, CHARBUFLEN-1, fpr)==NULL) break
prfb = readFileBuf
while(*prfb)
{
num = ReadStr(readStrBuf, prfb)
if(num == 0) fputc(*prfb++, fpw) // 没有读取成功
else if(num > 0) // 读入数字
{
prfb += (num >> 27) & 0xF // 移动读取的位数
if(isCompress) fprintf(fpw, "0 %d", num & 0x7FFFFFF) // 压缩模式写入数字,前面添加个数字0
else
{
num &= 0x7FFFFFF
if(num == 0) // 如果读到数字0
{
prfb += 1
num = ReadStr(readStrBuf, prfb) // 读取下一格数据串
if(num > 0)
{
prfb += (num >> 27) & 0xF // 移动读取的位数
fprintf(fpw, "%d", num & 0x7FFFFFF)
}
else fprintf(fpw, "0 ", num & 0x7FFFFFF) // 下一个不是数字
}
else if(num < curStrNum) fprintf(fpw, "%s", strTableDe[num]) // 解压模式写入字符串
else
{
printf("Error : %d, %d\n", num, curStrNum)
fprintf(fpw, "%d", num) // num大于已知的字符串数量,写入数字
}
}
}
else
{
num = -num
prfb += num // 移动读取的位数
if(isCompress)
{
num = getStrPos(readStrBuf)
if(num < 0) fprintf(fpw, "%s", readStrBuf) // 未出现过的字符串
else fprintf(fpw, "%d", num) // 写入位置
}
else
{
fprintf(fpw, "%s", readStrBuf)
if(curStrNum >= deTableLen) ReMallocDeTable() // 解压表长度不够,重新申请空间
strTableDe[curStrNum++] = copyNewStr(readStrBuf) // 加入解压表
}
}
}
}
if(isCompress) printf("Compress successful!\n")
else printf("Decompress Successful!\n")
over()
}
压缩是一种有效的减小数据量的方法,目前已经被广泛应用于各种类型的信息系统之中。
一种压缩文本文件的方法如下:
1. 原始文本文件中的非字母的字符,直接拷贝到压缩文件中;
2.
原始文件中的词(全部由字母组成),如果是第一次出现,则将该词加入到一个词的列表中,并拷贝到压缩文件中;否则该词不拷贝到压缩文件中,而是将该词在词的列表中的位置拷贝到压缩文件中。
3. 词的列表的起始位置为 1 。 词的定义为文本中由大小写字母组成的最大序列。大写字母和小写字母认为是不同的字母,即 abc 和 Abc
是不同的词。词的例子如下: * x-ray 包括两个词 x 和 ray * mary's 包括两个词 mary 和 s * a c-Dec 包括三个词 a 和
c 和 Dec 编写一个程序,输入为一组字符串,输出为压缩后的文本。
输入:
输入为一段文本,你可以假设输入中不会出现数字、每行的长度不会超过 80 个字符,并且输入文本的大小不会超过 10M。
输出:
压缩后的文本。
输入:
Please, please do it--it would please Mary very,
very much.
Thanks
输出:
Please, please do it--4 would 2 Mary very,
7 much.
Thanks
#include <stdlib.h>#include <stdio.h>
#include <string.h>
#define LEN 1<<20
int isArabic(char c){
return ('a'<=c&&c<='z') || ('A'<=c&&c<='Z')
}
int main()
{
char dict[LEN]
char *index[100000]
char buf[82]
int nWord=0
int i,j
char c
char *inFile="G:\\in.txt",*outFile="G:\\out.txt"
FILE *inp,*outp
if((inp=fopen(inFile,"r"))==NULL){
printf("cannot open\n")
exit(1)
}
if((outp=fopen(outFile,"w"))==NULL){
printf("out fail\n")
}
index[0]=dict
do{
/* get a word */
i=0
do{
c=fgetc(inp)
buf[i++]=c
}while(isArabic(c))
buf[i-1]=0
/* put it to dict */
if(i>1){
for(j=0j<nWordj++){
if(strcmp(index[j],buf)==0){
break
}
}
if(j==nWord){
strcpy(index[nWord],buf)
index[nWord+1]=index[nWord]+strlen(buf)+1
nWord++
/* printf("new: %s\n",buf)*/
}else{
sprintf(buf,"%d",j+1)
/* printf("found: %s\n",buf)*/
}
}
/* put it to output file */
if(c!=EOF)
fprintf(outp,"%s%c",buf,c)
else
fprintf(outp,"%s",buf)
}while(c!=EOF)
fclose(inp)
fclose(outp)
/* system("PAUSE")*/
return EXIT_SUCCESS
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)