zoukankan      html  css  js  c++  java
  • 数据压缩蓝桥杯

    欢迎访问我的新博客:http://www.milkcu.com/blog/

    原文地址:http://www.milkcu.com/blog/archives/1367192340.html

    前言

    本题摘自“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

        下面的程序实现了这个功能。请仔细阅读分析代码,填写空白的部分。

    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函数的作用是将缓冲数组中的变量输出到文件。

    为了验证代码正确性,在头部添加了一些预处理命令,才得以编译通过。

    源代码

    # 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);
    }

    最后答案

    1
    pop(pst, buf, c, w)
  • 相关阅读:
    ruby学习笔记(5)
    rails学习笔记(2)
    一个不错的rails2.0教程
    rails学习笔记(2)
    rails学习笔记(1)
    一个不错的rails2.0教程
    ruby学习笔记(6)
    ruby学习笔记(6)
    rails学习笔记(1)
    DELPHI的编译指令
  • 原文地址:https://www.cnblogs.com/milkcu/p/3808901.html
Copyright © 2011-2022 走看看