UVaoj 213:解码程序

传送门:题目链接

思路:做一个循环,每个循环都包含一下三步:

    第一步,就是用自己写的my_getline获取文件的一行header(为什么自己写?因为在联系C不想用C++而且gets不安全再者输入有空格等),其中要注意:获取一行字符串结束时要在对应地址末尾加上'\0'作为结束符;而结束获取的标志有EOF,'\n','\r'三者。

    第二步,处理header和二进制数(msg)的关系。这里注意到利用二进制及其题目本身的特点,想到用长度len去重。所以做一个table[len][max_value]表达(len,value)并存放对应的header中的字符。

    第三步,读取msg。由于输入的任意性(行随意),可以想象必须边读边操作边输出得到答案。所以根据步骤,我们做一个函数readint(num)用来读取msg中前num个数并返回其十进制值。这样就可以做一个循环,不断用readint(3)先获取接下来的编码长度(存为len),然后再不断readint(len)直到其值是2^len - 1时跳出……当readint(3)得到0时意味着此次循环结束。但是注意,末尾可能有换行符!所以用getchar()获取,得到的要么是EOF(最外围的循环结束),要么是换行符。

#include<stdio.h>
//#include<time.h>
//#include<string.h>

char header[6666];
char table[8][(1<<7)];//(len, value) -> char_in_header

int my_getline(char *header){
	//get the line of the stdin, terminated by '\n' or '\r' or EOF; return the length of the string
	int temp;
	int i = 0;
	while(EOF != (temp = getchar())){
		if(temp !='\n' && temp != '\r'){
			*(header + i) = (char)temp;
			i++;
		}
		else break;
	}
	//attention: put '\0' at the end
	*(header + i) = '\0';
	if(temp == EOF) return EOF;
	else return i;
}

int readbit(int num){
	//read num bits(0 or 1) from stdin, return the decimal value
	char temp;
	int ans = 0;
	int times = 0;
	while(times < num && (temp = getchar())){
		if(temp != '\r' && temp != '\n'){
			times++;
			ans += (temp - '0') * (1<<(num - times));
		}
	}
	return ans;
}

int main()
{
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	
	while(EOF != my_getline(header)){//input the header
		//cope with the header map to the bit codes
		int ptr = 0;
		for(int i = 1; header[ptr]; i++){
			int range = (1<<i) - 1;
			for(int j = 0; j < range && header[ptr]; j++){
				table[i][j] = header[ptr++];
			}
		}
		//input the message
		int len;
		while((len = readbit(3))){
			int value;
			while(1){
				value = readbit(len);
				if(value == (1 << len) - 1) break;
				putchar(table[len][value]);
			}
		}
		putchar('\n');
		if((len = getchar()) && len == EOF) break;//attention: read '\n' at the end!!! ,or EOF
	}
	
	//printf("Total time: %.4f s.", (double)clock()/CLOCKS_PER_SEC); 
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值