### 华为OD机试C卷- TLV解析 Ⅱ(Java & JS & Python)
#### 题目概述
本题目要求实现一种基于TLV(Tag-Length-Value)格式的解析器,针对一个给定的TLV格式的报文进行解析,并根据另一组给定的tag值列表来寻找并返回每条tag对应的数据长度和value在原始报文中的起始偏移量。
#### 报文格式解释
- **TLV格式**:报文按照Tag-Length-Value的结构进行编码。其中:
- Tag(标签):占用1个字节,用于标识数据类型或含义。
- Length(长度):同样占用1个字节,用于指定value部分的字节数。
- Value(值):根据Length字段指示的长度来确定。
#### 输入要求
- **输入字符串**:表示收到的消息包。字符串长度在10000以内,使用十六进制文本格式(字母为大写)展示消息包的数据。例如,“0F04ABABABAB”表示tag为15(0F),长度为4字节(04),值为ABABABAB。
- **需要匹配的tag数量**:表示后续给出的tag值数量。
- **待匹配的tag值**:按照升序排列给出的tag值列表,需要对这些tag值在输入报文中进行查找。
#### 输出要求
- 对于每一个需要匹配的tag,输出一行,包含两个整数:长度和偏移量。
- 如果tag存在于报文中,则输出对应的Length和Value的起始偏移量。
- 如果tag不存在于报文中,则输出“0 0”。
#### 解题思路
1. **解析输入报文**:遍历输入字符串,每次取出tag和length,然后计算value的起始偏移量。
2. **查找和匹配**:根据输入的tag列表,在解析过程中检查当前的tag是否存在于需要匹配的tag列表中。
3. **输出结果**:根据匹配结果输出长度和偏移量。
#### Java算法实现
下面是一个基于上述思路的Java实现示例:
```java
import java.util.Scanner;
public class TLVParser {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String packet = scanner.nextLine(); // 读取报文
int n = scanner.nextInt(); // 读取tag数量
scanner.nextLine(); // 跳过换行符
int[] tags = new int[n];
for (int i = 0; i < n; i++) {
tags[i] = scanner.nextInt(); // 读取每个tag
}
parseTLV(packet, tags);
}
private static void parseTLV(String packet, int[] tags) {
int offset = 0;
for (int tag : tags) {
int length = 0, valueOffset = -1;
boolean found = false;
while (offset < packet.length()) {
int currentTag = Integer.parseInt(packet.substring(offset, offset + 2), 16);
length = Integer.parseInt(packet.substring(offset + 2, offset + 4), 16);
if (currentTag == tag) {
found = true;
valueOffset = offset + 4;
break;
}
offset += 4 + length; // 移动到下一个TLV的开始
}
if (found) {
System.out.println(length + " " + valueOffset);
} else {
System.out.println("0 0"); // tag未找到
}
}
}
}
```
#### Python算法实现
下面是一个基于上述思路的Python实现示例:
```python
def parse_tlv(packet, tags):
offset = 0
results = []
for tag in tags:
length = 0
value_offset = -1
found = False
while offset < len(packet):
current_tag = int(packet[offset:offset + 2], 16)
length = int(packet[offset + 2:offset + 4], 16)
if current_tag == tag:
found = True
value_offset = offset + 4
break
offset += 4 + length
if found:
results.append(f"{length} {value_offset}")
else:
results.append("0 0")
return results
# 示例调用
packet = "0F04ABABABAB" # 示例报文
tags = [15, 16] # 示例待匹配的tag值
print(parse_tlv(packet, tags))
```
#### 小结
本题目的核心在于理解和实现TLV格式的解析逻辑,通过遍历输入字符串并根据tag进行匹配来完成解析任务。对于实际开发工作而言,这种类型的题目可以帮助开发者更好地理解二进制数据格式的解析方法。