TLV解码
题目描述
TLV编码是按[Tag Length Value]格式进行编码的,一段码流中的信元用Tag标识,Tag在码流中唯一不重复,Length表示信元Value的长度,Value表示信元的值。
码流以某信元的Tag开头,Tag固定占一个字节,Length固定占两个字节,字节序为小端序。
现给定TLV格式编码的码流,以及需要解码的信元Tag,请输出该信元的Value。
输入码流的16进制字符中,不包括小写字母,且要求输出的16进制字符串中也不要包含小写字母;码流字符串的最大长度不超过50000个字节。
输入描述
输入的第一行为一个字符串,表示待解码信元的Tag;
输入的第二行为一个字符串,表示待解码的16进制码流,字节之间用空格分隔。
输出描述
输出一个字符串,表示待解码信元以16进制表示的Value。
示例1
输入
31
32 01 00 AE 90 02 00 01 02 30 03 00 AB 32 31 31 02 00 32 33 33 01 00 CC
- 1
- 2
输出
2 33
- 1
说明
需要解析的信元的Tag是31,
从码流的起始处开始匹配,
第一个信元的Tag是32,信元长度为1(01 00,小端序表示为1);
第二个信元的Tag是90,其长度为2;
第三个信元的Tag是30,其长度为3;
第四个信元的Tag是31,其长度为2(02 00),
所以返回长度后面的两个字节即可,即32 33。
解题思路
题目要求解析一段以 TLV(Tag, Length, Value)格式编码的码流,找到特定的 Tag,并输出该Tag对应的 Value 部分。具体的TLV格式是这样的:
- Tag: 用一个字节表示,是信元的唯一标识符。
- Length: 用两个字节表示,表示信元的 Value 部分的长度,采用小端序,即低位字节在前。
- Value: 表示信元的值,根据 Length 的值来确定长度。
给定一个16进制的码流和要查找的Tag值,要求找到对应Tag的 Value,并以16进制格式输出。
关键点
-
小端序表示的Length:
- 小端序表示法即低字节在前,高字节在后。比如长度为
01 00
,表示的实际长度是 1(即 0001)。而02 00
表示长度 2(即 0002)。
- 小端序表示法即低字节在前,高字节在后。比如长度为
-
Tag 的固定长度是1字节, Length 固定是2字节,而 Value 的长度是根据 Length 来决定的。
示例详解
输入:
31
32 01 00 AE 90 02 00 01 02 30 03 00 AB 32 31 31 02 00 32 33 33 01 00 CC
- 1
- 2
- 目标Tag 是
31
。 - 码流 是:
32 01 00 AE 90 02 00 01 02 30 03 00 AB 32 31 31 02 00 32 33 33 01 00 CC
- 1
解析过程:
-
第一个信元:
- Tag:
32
- Length:
01 00
(小端序表示为 1) - Value:
AE
- 跳过该信元,因为 Tag 不匹配。
- Tag:
-
第二个信元:
- Tag:
90
- Length:
02 00
(小端序表示为 2) - Value:
01 02
- 跳过该信元,因为 Tag 不匹配。
- Tag:
-
第三个信元:
- Tag:
30
- Length:
03 00
(小端序表示为 3) - Value:
AB 32 31
- 跳过该信元,因为 Tag 不匹配。
- Tag:
-
第四个信元:
- Tag:
31
- Length:
02 00
(小端序表示为 2) - Value:
32 33
- Tag 匹配,输出 Value:
32 33
。
- Tag:
因此,输出结果为:
32 33
C语言代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include"stdlib.h"
#include"string.h"
#define MAX_LEN 50000
int main(){
char tag[3];
scanf("%s", tag);
char stream[MAX_LEN];
getchar();
fgets(stream,MAX_LEN,stdin);
char *vec[MAX_LEN];
int vec_size=0;
char *tmp = strtok(stream, " ");
while (tmp != NULL) {
vec[vec_size++] = tmp;
tmp = strtok(NULL," ");
}
for (int i = 0; i < vec_size; ) {
char *t = vec[i];
int len = atoi(vec[i + 1]) + 16 * atoi(vec[i + 2]);
if (strcmp(t, tag) == 0) {
for (int j = i + 3; j < i + 3 + len; j++) {
printf("%s", vec[j]);
}
printf("\n");
break;
}
else{
i = i + 2 + len + 1;
}
}
return 0;
}