一:题目
消息编码方案要求在两个部分中发送一个被编码的消息。第一部分:称为头,包含消息的字符。第二部分包含一个模式
表示信息。你必须写一个程序,可以解码这个消息。
(一)题目详细
你的程序的编码方案的核心是一个序列的“0和1”的字符串 。
0,
00,
01,
10,
000,
001,
010,
011,
100,
101,
110,
0000,
0001, . . . ,
1011,
1110,
00000, . . .
(对应数字个数n,则表示的编码为2^n-1个)
序列中长度为1的1个,长度为2的3个,长度为3的7个,长度为4的15个。如果相邻两个具有相同的长度,第二可从第一个加1(2进制)。注意有序列中没有全都是1的串。
键被映射到标题中的字符。也就是说,第一个键(0)映射在标题的第一个字符,第二键(
00)在头的二字符,k键映射到标头中的k个字符。
(二)案例
例如,假设标题是:AB#TANCnrtXc (可以包含空格)
然后0映射到A,00映射到B,01映射到#,10映射到T,000映射到A,…,110映射到X,0000映射到c.
该编码的信息包含0和1的和可能的回车,这是被忽略。消息分为段。一个段的前3位数字为二进制表示在段的键的长度。例如,如果前3位数字为010,则其余该段由长度为2(00,
01,或10)。段的结束是1的字符串
在段中的键长度相同。因此一段长度2的键是终止11。整个编码的信息被000终止(这将意味着一段段其中的按键有0个)。通过将该段中的键进行翻译,该消息被解码的标题字符已被映射。
(三)输入
输入文件包含多个数据集。每个数据集包含一个标题,这是在一个单独的行就其本身而言,和一个消息,它可能会延续几行。头的长度(
由三个数据位表示,0-7--->最大长度为七)是有限的唯一的事实,有一个关键字符串的最大长度为7(111的二进制)。--->(
由于最大长度为7,所以所表示的最大编码数为2^7-1)如果有多个在头一个字符的副本,然后几个键将映射到字符。编码信息仅包含0和1的,这是一个合法的编码,根据所描述的计划。那是,信息段的开始与适当的序列的序列长度和位数1,在任何给定的段的键都是相同的长度,并且它们都对应于字符标题。该消息以000终止
TNM AEIOU
0010101100011
1010001001110110011 //允许换行
11000 //这才是结束
$#**
\
0100000101101100011100101000 //结束
(四)输出
TAN ME
##*\$
二:代码实现
//信息解码,所有信息都属于ASCII码中
void Save_Encode(
char Code_Header[MAX_LEN],
char Encode[
7][
128],
int CHT_Status)
{
//开始向编码中存放数据
//获取编码头--注意含有空格
int ch,i=
0;
if (!CHT_Status)
//编码头没有获取
while (
1)
{
ch =
getchar();
Code_Header[i++] =
ch;
if (ch ==
'\n'||ch==
EOF)
break;
}
//将编码头数据放入编码中--最重要
int p,k =
0;
for (i =
1; i <=
7; i++
)
{
p = pow(
2.0, i*
1.0) -
1;
for (
int j =
0; j < p; j++
)
if (Code_Header[k] !=
'\n')
Encode[i][j] = Code_Header[k++
];
else
return;
}
}
//获取编码文本到Code_Textint Save_CodeText(
char Code_Text[MAX_LEN],
char Code_Header_Temp[MAX_LEN])
{
int ch, i;
while (
1)
{
memset(Code_Header_Temp, 0,
sizeof(Code_Header_Temp));
//获取一行到Code_Header_Temp
i =
0;
while (
1)
{
ch =
getchar();
Code_Header_Temp[i++] = ch==EOF?
'\n':ch;
if (ch ==
'\n'||ch==
EOF)
break;
}
if (Code_Header_Temp[
0] !=
'1' && Code_Header_Temp[
0] !=
'0')
return 1;
//将临时数据连接到Code_Text中
if (strlen(Code_Text)>
0)
Code_Text[strlen(Code_Text)-
1] =
0;
strcat(Code_Text, Code_Header_Temp);
}
return 0;
}
//获取指定个数二进制文本的数值
int getVal(
char* codeText,
int n)
{
int val =
0;
for (
int i = n -
1; i >=
0;i--
)
{
int k =
1;
for (
int j =
1; j <= i; j++
)
{
k *=
2;
}
val += (*codeText-
'0')*
k;
codeText++
;
}
return val;
}
//处理数据,进行输出void Deal_CodeData(
char Encode[][
128],
char*
Code_Text)
{
int len,val,chk,k=
0;
while (
1)
{
//找到编码长度
len = getVal(&Code_Text[k],
3);
Code_Text +=
3;
//步长向后移动3个
if (len ==
0)
//3个0退出
return;
chk = pow(
2.0, len*
1.0) -
1;
//根据长度,获取值
while (
1)
{
val =
getVal(Code_Text, len);
Code_Text +=
len;
if (val ==
chk)
break;
//去对应位置找编码数据
printf(
"%c", Encode[len][val]);
}
}
}
void func03()
{
FILE* fi = freopen(
"data.in",
"r", stdin);
freopen("data.out",
"w", stdout);
//因为前三位表示长度,所以最长为7位其中七位编码最大为1111110可以表示2^7-1个数所以将列数设置为2^7=128
char Encode[
8][
128];
//操作二维数组,我们直接从1开始,忽略0带来的麻烦
//注意:每行只有2^n - 1 个有效
char Code_Header[MAX_LEN];
//存放编码头
char Code_Text[MAX_LEN];
//存放编码文本
char Code_Header_Temp[MAX_LEN];
//存放有可能的编码头
int CHT_Status=
0;
//是否从临时数组中读取编码头
memset(Code_Header_Temp, 0,
sizeof(Code_Header_Temp));
//开始进行读取处理数据
while (!
feof(fi))
{
memset(Code_Text, 0,
sizeof(Code_Text));
memset(Encode, 0,
sizeof(Encode));
memset(Code_Header, 0,
sizeof(Code_Header));
//将编码头数据保存到编码数组中
if (CHT_Status)
strcpy(Code_Header, Code_Header_Temp);
Save_Encode(Code_Header, Encode,CHT_Status);
//获取编码文本--文本可能不在同一行(难点)
//方法:一次获取一个字符
CHT_Status =
Save_CodeText(Code_Text,Code_Header_Temp);
//开始处理数据,并打印出来
Deal_CodeData(Encode,Code_Text);
printf("\n");
}
freopen("CON",
"r", stdin);
freopen("CON",
"w", stdout);
}
转载于:https://www.cnblogs.com/ssyfj/p/10837824.html