`
C_SHaDow
  • 浏览: 49539 次
  • 性别: Icon_minigender_1
  • 来自: 大同
社区版块
存档分类
最新评论
阅读更多

课程设计名称:差分法求数据压缩
题目:一数据文件中存放着若干个8位有符号数(补码),其相邻两数之间差值不超过-8至7。对这种变化缓慢的数据可采用差分方法进行压缩。即第一个数据不变,其后的数据取与前一数据的差值并用4位二进制补码表示,两个差值拼成一个字节,前一个差值放在高4位,后一个差值放在低4位。 例如: 原数据(X[n]):0x23,0x27,0x2A,0x29,0x22,…… 压缩后(Y[n]):0x23, 0x43, 0xF9 ,…… 1、编程按上述方法进行压缩,结果保存在另一文件中。 2、能够实现将压缩后的文件解压。

 

虽然是帮同学做一道题目,我还是认真分析了一下的。

首先,考虑测试用的文件。不能用UtraEditor去写16进制文件吧,况且我只知道它能以16进制方式显示文件内容……于是,我用内容为“abcdefghgfedcba”的文本文件作为测试文件。

其次,我分析了一下程序的基本流程。获取参数->读取文件->压缩/解压->写出文件。

 

在获取参数上,我考虑了两种方式。一种是直接用程序启动参数,在main函数参数列表里的。另一种是给用户提示信息,用户输入文件路径并回车确认输入。在使用第二种方式时我用到的C函数是char *fgets(char *s, int n, FILE *stream);

char input_file[256] = "";    // 定义保存文件路径的变量

printf("请输入文件路径:");    // 给出提示信息
fgets(input_file,256,stdin); // 读取控制台输入

 

其中stdin指控制台输入。这里还遇到一个问题,input_file获取的值需要trim操作,而C语言对字符传的操作米有trim函数。无奈,从网上拷了一个漂亮的实现。希望拷走的BODY同样用着愉快。

//////////////////////////////////////////////////////
char* trim(char* desc,char* src,char* seps)
{
char* token=NULL;
   /* Establish string and get the first token: */
   token = strtok(src, seps);
   while( token != NULL )
   {
      /* While there are tokens in "string" */
      strcat(desc,token);
      /* Get next token: */
      token = strtok( NULL, seps );
   }
   return desc;
}

 
文件读写用到的C函数是

FILE *stream=fopen(const char *filepath, const char *op);

int i=fgetc(FILE *stream);

int fputc(int i, FILE *stream);

int fclose(FILE *stream);

加入输出缓冲后用到的C函数是

int fwrite(const void* buf, int size, int count, FILE *stream);

缓冲区的实现分为三个步骤:定义缓冲区数组->将数据放到缓冲区->判断缓冲区是否已满(满就输出)->最后判断缓冲区是否为空(空就输出)。

byte buffer[1024];                           // 缓冲区
int index = 0;                                // 缓冲区下标

......

buffer[index] = chout;                  // 将数据放入缓冲区                
index++;                                      // ditto
if(1024 == index) {                      // 判断缓冲区是否已满 
   fwrite(buffer, 1024, 1, fpout);
    index = 0;                                // 清空缓冲区
}

......

if(index != 0) {                             // 判断缓冲区是否为空
    fwrite(buffer, index, 1, fpout);
}

 

这里需要注意的是,fwrite函数是针对内存操作的,一个int数组做缓冲区和一个byte数组做缓冲区是绝对不同的。虽然你写size=1;count=1024,但是对于int数组缓冲区来说只输出来256个数据。。。呵呵,这个地方真的很变态啊!!!

 

对于压缩和解压的算法实现上,我采用最保险的编程,尽量一行代码只操作一个变量。

 

// 压缩
    int ch,chfollow,tmp,chout=5;
    fputc((ch = fgetc(fpin)), fpout); //第一个数据不变
    long fs = filesize(fpin);  
    fputc(fs%2, fpout);    // 保存文件奇偶性
    while((chfollow = fgetc(fpin)) != EOF) {
		tmp = chfollow - ch;   // 计算差值
		if(tmp<0) {   // 将负差转化为正数
			tmp = 8 + (8 - (0 - tmp));
		}
    	if(chout<8 && chout>0){
    		chout = tmp << 4; // 保存高位
	    }else{
    		chout += tmp;  // 保存低位
    		
    		printf("%d ", chout);
			// fputc(chout, fpout);
    		buffer[index] = chout;
    		index++;
    		if(1024 == index) {
		    	fwrite(buffer, 1024, 1, fpout);
		    	index = 0;
		    }
    		
    		chout = 5;
    	}
    	ch = chfollow;
    }
    if(chout>8 || chout==0) {
    	printf("%d ", chout);
    	// fputc(chout, fpout);
    	buffer[index] = chout;
    	index++;
    	fwrite(buffer, index, 1, fpout);
    } else {
    	if(index != 0) {
    		fwrite(buffer, index, 1, fpout);
    	}
    }

 

// 解压
    int flag,ch,chfollow,tmp,chout=0;
    fputc((ch = fgetc(fpin)), fpout);   // 第一个数据不变
    flag = fgetc(fpin);     // 数据奇偶性
    while((chfollow = fgetc(fpin)) != EOF) {
    	printf("%d ", chfollow);
    	tmp = chfollow;
		
		chfollow = chfollow >> 4;  // 还原前一个数据
		chout = add(ch, chfollow);
		
    	buffer[index] = chout;
    	index++;
		
		tmp = tmp & 15;  // 还原后一个数据
		chout = add(chout, tmp);
		
		buffer[index] = chout;
    	index++;
    	
    	if(1024 == index) {
		    fwrite(buffer, 1024, 1, fpout);
		    index = 0;
		}
		
    	ch = chout;
    }
    if(index != 0) {
    	fwrite(buffer, index, 1, fpout);
    }
    if(0 == flag) {  // 根据奇偶性删除
    	fseek(fpout, -1, SEEK_CUR);
    	fputc(EOF, fpout);
    }

对于源文件长度奇偶性的分析可用与解压时对最后一位数据做更加精准的还原,这里不细分析。。。。。。

 

啊啊啊啊啊啊,就此,复习了C的文件读写,将当时Java文件压缩的小项目用C实现了一哈,感脚良好……

3
0
分享到:
评论

相关推荐

    基于压缩感知和字典学习的背景差分法 (2012年)

    针对当使用背景差分法时,背景存在突变和渐变、图像数据的冗余和伪前景对目标检测的干扰等问题,提出一种基于稀疏表示和字典学习的背景差分法。该方法首先训练视频流得到其数据字典,并根据数据字典学习与稀疏表示理论...

    MATLAB常用算法

    Newtonforward 求已知数据点的前向牛顿差分插值多项式 Newtonback 求已知数据点的后向牛顿差分插值多项式 Gauss 求已知数据点的高斯插值多项式 Hermite 求已知数据点的埃尔米特插值多项式 SubHermite 求已知数据点...

    MATLAB语言常用算法程序集

    Newtonforward 求已知数据点的前向牛顿差分插值多项式 Newtonback 求已知数据点的后向牛顿差分插值多项式 Gauss 求已知数据点的高斯插值多项式 Hermite 求已知数据点的埃尔米特插值多项式 SubHermite 求已知数据点的...

    使用 PCA 和 WDR 技术的 CT 扫描和 X 射线医学图像压缩的性能分析-研究论文

    图像压缩是数据压缩的一个子集,在医学领域起着至关重要的作用。 CT、MRI、PET 扫描和 X 射线图像等医学图像是海量数据,应进行压缩以方便存储容量,同时不丢失其详细信息,以便正确诊断患者。 现在,人工神经网络在...

    算法导论(part1)

    它深入浅出地介绍了大量的算法及相关的数据结构,以及用于解决一些复杂计算问题的高级策略(如动态规划、贪心算法、平摊分析等),重点在于算法的分析和设计。对于每一个专题,作者都试图提供目前最新的研究成果及样例...

    大数据预处理技术.pdf

    ⼤数据预处理技术 学习了⽜琨⽼师的课程后整理的学习笔记,⽤于... 数量规约:⽤替代的、较⼩的数据表⽰形式替换原数据 具体⽅法包括:抽样和数据⽴⽅体聚集 数据压缩:⽆损压缩:能从压缩后的数据重构恢复原来的数据,

    matlab源码求一元函数-Motion-Detection-System-Based-On-Background-Reconstructio

    本设计结合FPGA自身的并行流水特性,对传统的帧间差分法进行改进,将前一帧从640×480×8bit的灰度图像通过2×2的窗口累加压缩为320×240×10bit的灰度图像作为缓存帧,在帧差过程中再重建展开用于运算,节省缓存帧图像...

    地理信息系统算法基础.rar

    5.2.4差分映射法 5.2.5四叉树编码 5.3拓扑关系的生成 5.3.1基本数据结构 5.3.2弧段的预处理 5.3.3结点匹配算法 5.3.4建立拓扑关系 思考题 第6章空间度量算法 6.1直线和距离 6.1.1直线 6.1.2直线...

    基于TMS320DM368的智能高清监控系统的研究与实现

    利用三帧差分法检测出运动目标后,用改进的Camshifi算法对目标进行跟踪。从三个方面对Camshifl算法进行改进:只对目标的局部背景区域进行反向投影计算;计算目标与干扰区域的颜色相似系数,当系数大于阈值时,采用H...

    地理信息系统算法基础

    3.3仿射变换3.4地图投影变换3.4.1概述3.4.2地球椭球体的相关公式...数据压缩算法5.2栅格数据的压缩5.2.1链式编码5.2.2游程长度编码5.2.3块式编码5.2.4差分映射法5.2.5四叉树编码5.3拓扑关系的生成...

    AcWing算法基础课模板大全

    前缀和与差分 双指针算法 位运算 离散化 区间合并 数据结构 —— 代码模板链接 常用代码模板2——数据结构 链表与邻接表:树与图的存储 栈与队列:单调队列、单调栈 kmp Trie 并查集 堆 Hash表 搜索与图论 —— ...

    电源技术中的FDTD模拟软件电磁建模模块的研究和实现

    l 引 言时域有限差分法(Fnite Difference Time Domain,FDTD)是1966年K.S.Yee首先提出的一种以Maxwell方程为基础的解决电磁场问题的数值计算方法[1]。FDTD算法将Maxwell方程中的两个旋度方程直接转化为差分形式,...

    建议收藏算法基础课模板大全

    前缀和与差分 双指针算法 位运算 离散化 区间合并 数据结构 —— 代码模板链接 常用代码模板2——数据结构 链表与邻接表:树与图的存储 栈与队列:单调队列、单调栈 kmp Trie 并查集 堆 Hash表 搜索与图论 —— ...

    数学建模-算法-汇总

    算法大全第16章_差分方程模型.pdf 算法大全第17章_马氏链模型.pdf 算法大全第18章_变分法模型.pdf 算法大全第19章_神经网络模型.pdf 算法大全第20章_偏微分方程的数值解.pdf 算法大全第21章_目标规划.pdf 算法大全第...

    IOI国家集训队论文集1999-2019

    + [差分约束系统](#差分约束系统) + [平面图](#平面图) + [2-SAT](#2-sat) + [最小生成树](#最小生成树) + [二分图](#二分图) + [Voronoi图](#voronoi图) + [偶图](#偶图) * [树](#树) + [树](#树-1) + ...

    特征工程.ipynb

    过滤式(filter):先对数据进行特征选择,然后在训练学习器,常见的方法有 Relief/方差选择发/相关系数法/卡方检验法/互信息法; 包裹式(wrapper):直接把最终将要使用的学习器的性能作为特征子集的评价准则,...

    算法心得:高效算法的奥秘(原书第2版).[美]Henry S.Warren,Jr(带详细书签).pdf

    10.3 在除数不是2的幂时求带符号除法及余数 183 10.3.1 除以3 183 10.3.2 除以5 184 10.3.3 除以7 185 10.4 除数大于等于2的带符号除法 185 10.4.1 算法 187 10.4.2 算法可行性证明 187 10.4.3 证明乘积正确...

    ACM算法竞赛常用代码

    图论(图论模型的建立,平面图,欧拉公式与五色定理,求强连通分量,求割点和桥,欧拉回路,AOV问题,AOE问题,最小生成树的三种算法,最短路的三种算法,标号法,差分约束系统,验证二分图,Konig定理,匈牙利算法...

Global site tag (gtag.js) - Google Analytics