程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 數據壓縮--藍橋杯

數據壓縮--藍橋杯

編輯:C++入門知識

前言
本題摘自“2012年第三屆藍橋杯全國軟件大賽決賽(C本科)”第2題,由MilkCu整理。

題目描述
    某工業監控設備不斷發回采樣數據。每個數據是一個整數(0到1000之間)。各個數據間用空白字符(空格,TAB或回車換行)分隔。這些數據以文本形式被存儲在文件中。
    因為大多數時候,相鄰的采樣間隔數據是相同的,可以利用這個特征做數據的壓縮存儲。其方法是:對n(n>1)個連續相同的數字只記錄n和該數字本身;對m(m>0)個連續不重復的數字,則記錄 m*-1 和這些數字本身(之所以用負數,是為了與第一種情況區分,便於解壓縮)。

    例如:采樣數字:
    12 34 34 25 25 25 25 11 15 17 28 14 22 22 22 13
    則根據上述規則變化後:
    -1 12 2 34 4 25 -5 11 15 17 28 14 3 22 -1 13

    下面的程序實現了這個功能。請仔細閱讀分析代碼,填寫空白的部分。

[cpp]
void pop(int s, int* buf, int c, FILE* fp) 

    int i; 
    if(s) 
    { 
        fprintf(fp, "%d %d ", c, *buf); 
    } 
    else 
    { 
        fprintf(fp, "%d ", -c); 
        for(i=0; i<c; i++) 
        { 
            fprintf(fp, "%d ", buf[i]); 
        } 
    } 

 
void dopack(FILE* r, FILE* w) 

    int buf[BUF_N]; 
 
    int pos = 0;  // 下一個數字在buf中將要存放的位置  
    int c = 0;    // 當前段已讀入的整數個數  
    int pst;  
    int cst; 
 
    while(fscanf(r, "%d", buf+pos)==1) 
    { 
        if(c==0) 
        { 
            c = pos = 1; 
            continue; 
        } 
 
        if(c==1) 
        { 
            pst = buf[0] == buf[1]; 
            pos = pos + 1 - pst; 
            c = 2; 
            continue; 
        } 
         
        cst = buf[pos-1] == buf[pos]; 
        if(pst && !cst) 
        { 
            pop(pst, buf, c, w); 
            buf[0] = buf[1]; 
            c = pos = 1; 
            pst = cst; 
        } 
        else if(!pst && cst || pos == BUF_N-1) 
        { 
            pop(pst, buf, c-1, w); 
            buf[0] = buf[pos-1]; 
            c = 2; 
 
            if(!cst) 
            { 
                buf[1] = buf[pos]; 
                pos = 2; 
            } 
            else 
            { 
                pos = 1; 
                pst = ______________;  // 填空1  
            } 
        } 
        else 
        { 
            c++; 
            if(!pst) pos++; 
        } 
    } // while  
 
    if(c>0) _____________________________;   // 填空2  

 
void main() 

    FILE* rfp; 
    FILE* wfp; 
 
    if((rfp=fopen(RFILE, "r")) == NULL) 
    { 
        printf("can not open %s!\n", RFILE); 
        exit(1); 
    } 
 
    if((wfp=fopen(WFILE, "w")) == NULL) 
    { 
        printf("can not open %s!\n", WFILE); 
        fclose(rfp); 
        exit(2); 
    } 
 
    dopack(rfp, wfp); 
 
    fclose(wfp); 
    fclose(rfp); 

void pop(int s, int* buf, int c, FILE* fp)
{
 int i;
 if(s)
 {
  fprintf(fp, "%d %d ", c, *buf);
 }
 else
 {
  fprintf(fp, "%d ", -c);
  for(i=0; i<c; i++)
  {
   fprintf(fp, "%d ", buf[i]);
  }
 }
}

void dopack(FILE* r, FILE* w)
{
 int buf[BUF_N];

 int pos = 0;  // 下一個數字在buf中將要存放的位置
 int c = 0;    // 當前段已讀入的整數個數
 int pst;
 int cst;

 while(fscanf(r, "%d", buf+pos)==1)
 {
  if(c==0)
  {
   c = pos = 1;
   continue;
  }

  if(c==1)
  {
   pst = buf[0] == buf[1];
   pos = pos + 1 - pst;
   c = 2;
   continue;
  }
  
  cst = buf[pos-1] == buf[pos];
  if(pst && !cst)
  {
   pop(pst, buf, c, w);
   buf[0] = buf[1];
   c = pos = 1;
   pst = cst;
  }
  else if(!pst && cst || pos == BUF_N-1)
  {
   pop(pst, buf, c-1, w);
   buf[0] = buf[pos-1];
   c = 2;

   if(!cst)
   {
    buf[1] = buf[pos];
    pos = 2;
   }
   else
   {
    pos = 1;
    pst = ______________;  // 填空1
   }
  }
  else
  {
   c++;
   if(!pst) pos++;
  }
 } // while

 if(c>0) _____________________________;   // 填空2
}

void main()
{
 FILE* rfp;
 FILE* wfp;

 if((rfp=fopen(RFILE, "r")) == NULL)
 {
  printf("can not open %s!\n", RFILE);
  exit(1);
 }

 if((wfp=fopen(WFILE, "w")) == NULL)
 {
  printf("can not open %s!\n", WFILE);
  fclose(rfp);
  exit(2);
 }

 dopack(rfp, wfp);

 fclose(wfp);
 fclose(rfp);
}【注意】
    只填寫缺少的部分,不要抄寫已有的代碼。
    所填寫代碼不超過1條語句(句中不會含有分號)
    所填代碼長度不超過256個字符。
    答案寫在“解答.txt”中,不要寫在這裡!

分析
該題目若是編程題,讓自己寫代碼,難度貌似第一點。但是它是填空題,可以在不讀懂每一條語句的情況下得出答案,當然都讀懂更好。

pop函數的作用是將緩沖數組中的變量輸出到文件。

為了驗證代碼正確性,在頭部添加了一些預處理命令,才得以編譯通過。

源代碼
[cpp]
# include <stdio.h>  
# include <stdlib.h>  
# define BUF_N 1000  
# define RFILE "rfile.txt"  
# define WFILE "wfile.txt"  
void pop(int s, int* buf, int c, FILE* fp) 

    int i; 
    if(s) 
    { 
        fprintf(fp, "%d %d ", c, *buf); 
    } 
    else 
    { 
        fprintf(fp, "%d ", -c); 
        for(i=0; i<c; i++) 
        { 
            fprintf(fp, "%d ", buf[i]); 
        } 
    } 

 
void dopack(FILE* r, FILE* w) 

    int buf[BUF_N]; 
 
    int pos = 0;  // 下一個數字在buf中將要存放的位置  
    int c = 0;    // 當前段已讀入的整數個數  
    int pst;  
    int cst; 
 
    while(fscanf(r, "%d", buf+pos)==1) 
    { 
        if(c==0) 
        { 
            c = pos = 1; 
            continue; 
        } 
 
        if(c==1) 
        { 
            pst = buf[0] == buf[1];  //前兩個是否相等   
            pos = pos + 1 - pst; 
            c = 2; 
            continue; 
        } 
         
        cst = buf[pos-1] == buf[pos];  //後兩個是否相等   
        if(pst && !cst) 
        { 
            pop(pst, buf, c, w); 
            buf[0] = buf[1]; 
            c = pos = 1; 
            pst = cst; 
        } 
        else if(!pst && cst || pos == BUF_N-1) 
        { 
            pop(pst, buf, c-1, w); 
            buf[0] = buf[pos-1]; 
            c = 2; 
 
            if(!cst) 
            { 
                buf[1] = buf[pos]; 
                pos = 2; 
            } 
            else 
            { 
                pos = 1; 
                pst = 1;  // 填空1  
            } 
        } 
        else 
        { 
            c++; 
            if(!pst) pos++; 
        } 
    } // while  
 
    if(c>0) pop(pst, buf, c, w);   // 填空2  

 
int main() 

    FILE* rfp; 
    FILE* wfp; 
 
    if((rfp=fopen(RFILE, "r")) == NULL) 
    { 
        printf("can not open %s!\n", RFILE); 
        exit(1); 
    } 
 
    if((wfp=fopen(WFILE, "w")) == NULL) 
    { 
        printf("can not open %s!\n", WFILE); 
        fclose(rfp); 
        exit(2); 
    } 
 
    dopack(rfp, wfp); 
 
    fclose(wfp); 
    fclose(rfp); 

# include <stdio.h>
# include <stdlib.h>
# define BUF_N 1000
# define RFILE "rfile.txt"
# define WFILE "wfile.txt"
void pop(int s, int* buf, int c, FILE* fp)
{
 int i;
 if(s)
 {
  fprintf(fp, "%d %d ", c, *buf);
 }
 else
 {
  fprintf(fp, "%d ", -c);
  for(i=0; i<c; i++)
  {
   fprintf(fp, "%d ", buf[i]);
  }
 }
}

void dopack(FILE* r, FILE* w)
{
 int buf[BUF_N];

 int pos = 0;  // 下一個數字在buf中將要存放的位置
 int c = 0;    // 當前段已讀入的整數個數
 int pst;
 int cst;

 while(fscanf(r, "%d", buf+pos)==1)
 {
  if(c==0)
  {
   c = pos = 1;
   continue;
  }

  if(c==1)
  {
   pst = buf[0] == buf[1];  //前兩個是否相等
   pos = pos + 1 - pst;
   c = 2;
   continue;
  }
  
  cst = buf[pos-1] == buf[pos];  //後兩個是否相等
  if(pst && !cst)
  {
   pop(pst, buf, c, w);
   buf[0] = buf[1];
   c = pos = 1;
   pst = cst;
  }
  else if(!pst && cst || pos == BUF_N-1)
  {
   pop(pst, buf, c-1, w);
   buf[0] = buf[pos-1];
   c = 2;

   if(!cst)
   {
    buf[1] = buf[pos];
    pos = 2;
   }
   else
   {
    pos = 1;
    pst = 1;  // 填空1
   }
  }
  else
  {
   c++;
   if(!pst) pos++;
  }
 } // while

 if(c>0) pop(pst, buf, c, w);   // 填空2
}

int main()
{
 FILE* rfp;
 FILE* wfp;

 if((rfp=fopen(RFILE, "r")) == NULL)
 {
  printf("can not open %s!\n", RFILE);
  exit(1);
 }

 if((wfp=fopen(WFILE, "w")) == NULL)
 {
  printf("can not open %s!\n", WFILE);
  fclose(rfp);
  exit(2);
 }

 dopack(rfp, wfp);

 fclose(wfp);
 fclose(rfp);
}最後答案
[cpp]   
pop(pst, buf, c, w) 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved