E-TLV解码(100p)
TLV解码
问题描述
TLV(Tag-Length-Value)编码是一种常用的数据编码格式。在这个编码中,每个数据元素由三部分组成:
- Tag:标识数据类型,固定占用 1 个字节。
- Length:表示 Value 的长度,固定占用 2 个字节,采用小端序。
- Value:实际数据内容,长度由 Length 决定。
现给定一个 TLV 格式编码的 16 进制字符串(码流),以及需要解码的特定 Tag,请解析并输出该 Tag 对应的 Value。
输入格式
输入包含两行:
- 第一行是一个字符串,表示需要解码的 Tag。
- 第二行是一个字符串,表示 TLV 编码的 16 进制码流,字节之间用空格分隔。
输出格式
输出一个字符串,表示解码后的 Value,以 16 进制表示。
样例输入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
32 33
样例解释
样例1 | 需要解析的信元的 Tag 是 31。从码流的起始处开始匹配: 1. 第一个信元的 Tag 是 32,长度为 1(01 00,小端序表示为 1); 2. 第二个信元的 Tag 是 90,长度为 2; 3. 第三个信元的 Tag 是 30,长度为 3; 4. 第四个信元的 Tag 是 31,长度为 2(02 00)。 因此,返回长度后面的两个字节,即 32 33。 |
数据范围
- 输入的 16 进制字符不包含小写字母。
- 要求输出的 16 进制字符串中也不包含小写字母。
- 码流字符串的最大长度不超过 50000 个字节。
题解
模拟
这道题目要求我们解析 TLV(Tag-Length-Value)编码的数据流。解题的关键在于正确理解 TLV 的结构和小端序的概念。
首先,我们需要逐字节遍历输入的码流。对于每个数据元素,我们需要:
- 读取 1 个字节作为 Tag。
- 读取接下来的 2 个字节作为 Length,注意使用小端序解析。
- 根据 Length 的值,读取相应长度的 Value。
在这个过程中,我们需要特别注意以下几点:
-
小端序的处理:Length 占用两个字节,但是低位字节在前,高位字节在后。例如,"01 00" 表示长度为 1,而不是 256。
-
16 进制字符串的处理:输入的码流是以空格分隔的 16 进制字符串,我们需要正确地将其转换为实际的字节值。
-
Tag 的匹配:我们需要持续遍历码流,直到找到与输入 Tag 匹配的数据元素。
-
Value 的提取:一旦找到匹配的 Tag,我们需要根据其 Length 提取正确长度的 Value。
参考代码
- Python
def parse_tlv(tag, stream):
# 将空格分隔的16进制字符串转换为字节列表
bytes_list = [int(b, 16) for b in stream.split()]
i = 0
while i < len(bytes_list):
# 读取当前Tag
current_tag = bytes_list[i]
i += 1
# 读取Length(小端序)
length = bytes_list[i] + (bytes_list[i+1] << 8)
i += 2
# 如果找到匹配的Tag,返回Value
if current_tag == int(tag, 16):
return ' '.join([f'{b:02X}' for b in bytes_list[i:i+length]])
# 否则跳过当前Value
i += length
# 如果没有找到匹配的Tag,返回空字符串
return ''
# 读取输入
tag = input().strip()
stream = input().strip()
# 解析TLV并输出结果
result = parse_tlv(tag, stream)
print(result)
- C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 100000
// 将16进制字符转换为整数
int hex_to_int(char c) {
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
return -1;
}
// 解析TLV编码
char* parse_tlv(int tag, unsigned char* stream, int stream_len) {
int i = 0;
while (i < stream_len) {
int current_tag = stream[i++];
int length = stream[i] + (stream[i+1] << 8);
i += 2;
if (current_tag == tag) {
char* result = (char*)malloc(length * 3);
for (int j = 0; j < length; j++) {
sprintf(result + j*3, "%02X ", stream[i+j]);
}
result[length*3-1] = '\0';
return result;
}
i += length;
}
return "";
}
int main() {
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
算法刷题笔记 文章被收录于专栏
本专栏收集并整理了一些刷题笔记