例題 4-4 資訊解碼 (Message Decoding) UVa 213
阿新 • • 發佈:2019-01-31
題意:
給一個編碼頭和一串編碼(編碼可以換行),編碼頭根據以下規則對應編碼{ 考慮下面的01串: 0,00,01,10,000,001,010,101,110,0000,0001.....首先是長度為1的串,然後是長度為二的串,以此類推。並且每一段長度的數字從0到(1<<n)-1(第n段)排列,即題目中所說不包括全為1的串。
編碼文字由多個小節組成,每小節前三位數字表示該小節中每個編碼的長度(例010表示編碼長度為2),然後是各個字元的編碼,每小節以全1結束。例第一小節:00101。
你的任務是編寫一個解碼程式,將輸入的編碼轉化為對應編碼頭中字元的句子輸出。
實現:
#include<stdio.h> #include<string.h> int code[8][1<<7]; int readchar()//讀取字元 拋棄換行符 { while(1){ int ch = getchar(); if(ch != '\n' && ch != '\r') return ch; } } int readint(int c) //把c位 二進位制數轉換為十進位制數 { int v = 0; while(c--){ v = v*2 + readchar()-'0'; } return v; } int readcodes()//讀取編碼頭 這裡讀取的時候 長度為len的 第 i 位(i就是相應的編碼的二進位制對應的十進位制的值) { memset(code, 0, sizeof(code));//對於單獨讀取編碼頭第一個字元時候這個 不必要 code[1][0] = readchar();//讀取下一串編碼頭時候 單獨用readchar()讀取第一個 它可以拋棄換行符 for(int len = 2; len <= 7; len++ ){ for(int i = 0; i < (1<<len)-1; i++ ){ int ch = getchar(); if(ch == EOF) return 0; if(ch == '\n' || ch == '\r') return 1; code[len][i] = ch; // code 中儲存的就是 相應字元的ASCII } } return 1; } void printcodes()//題解用不到 用於除錯 { for(int len = 1; len <= 7; len++ ){ for(int i = 0; i < (1<<len)-1; i++ ){ if(code[len][i] == 0) return; printf("code[%d][%d] = %c\n",len, i, code[len][i]); } } } int main() { //freopen("C:\\Users\\zhangwei\\Desktop\\input.txt","r",stdin); while(readcodes()){ // printcodes(); while(1){ int len = readint(3);//讀取編碼的長度 if(len == 0) break; while(1){ int v = readint(len); if(v == (1<<len)-1)//判斷 是否是該長度下的結束位置(全為1) break; putchar(code[len][v]);//輸出相應ASCII 對應的字元 } } putchar('\n'); } return 0; }
注意: (1)putchar() 可以把 ASCII 轉換為對應的 字元輸出
(2)還有的 是code[len][i] 中 的i 對應的 就是當前二進位制位長度下的 編碼字元對應的 十進位制的值
例如 code[3][2] 對應的就是二進位制位為三位時候 對應的 010(十進位制為2)
(3)readchar()中 可以拋棄 換行符 並且在沒讀取一個字元的時候 快取區裡的這個字元就出去了(不再存在於緩衝區)
這也就使得能夠依次讀取輸入的所有字元