差分法c语言源程序,差分法求数据压缩
課程設計名稱:差分法求數據壓縮
題目:一數據文件中存放著若干個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實現了一哈,感腳良好……
Projects.rar (27 KB)
下載次數: 10
總結
以上是生活随笔為你收集整理的差分法c语言源程序,差分法求数据压缩的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言日志级别和作用,自己写的C语言通用
- 下一篇: c语言中return语句例子,C语言 r