2025年A卷:最新华为OD机试

最新华为OD机试

题目描述

TLV编码是按格式进行编码的,一段码流中的信元用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

输出

2 33

说明

需要解析的信元的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格式是这样的:

  1. Tag: 用一个字节表示,是信元的唯一标识符。
  2. Length: 用两个字节表示,表示信元的 Value
    部分的长度,采用小端序,即低位字节在前。
  3. Value: 表示信元的值,根据 Length 的值来确定长度。

给定一个16进制的码流和要查找的Tag值,要求找到对应Tag的
Value,并以16进制格式输出。

关键点
  1. 小端序表示的Length

    • 小端序表示法即低字节在前,高字节在后。比如长度为
      01 00,表示的实际长度是 1(即 0001)。而 02 00 表示长度 2(即
      0002)。
  2. 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
  • 目标Tag31

  • 码流 是:

    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 不匹配。
  2. 第二个信元:

    • Tag: 90
    • Length: 02 00(小端序表示为 2)
    • Value: 01 02
    • 跳过该信元,因为 Tag 不匹配。
  3. 第三个信元:

    • Tag: 30
    • Length: 03 00(小端序表示为 3)
    • Value: AB 32 31
    • 跳过该信元,因为 Tag 不匹配。
  4. 第四个信元:

    • Tag: 31
    • Length: 02 00(小端序表示为 2)
    • Value: 32 33
    • Tag 匹配,输出 Value32 33

因此,输出结果为:

32 33

Java

import java.util.Scanner;public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        // 输入待解码信元的Tag
        String tag = sc.nextLine();
        
        // 输入16进制码流
        String line = sc.nextLine();
        
        // 将16进制码流按空格分割成字符串数组
        String[] hexArray = line.split(" ");
        
        int index = 0;
        while (index < hexArray.length) {
            // 获取当前信元的长度
            int length = Integer.parseInt(hexArray[index + 2] + hexArray[index + 1], 16);
            
            // 如果当前信元的Tag与待解码信元的Tag相同
            if (hexArray[index].equals(tag)) {
                StringBuilder sb = new StringBuilder();
                
                // 将当前信元的Value拼接到StringBuilder中
                for (int i = index + 3; i < index + 3 + length; i++) {
                    sb.append(hexArray[i]).append(" ");
                }
                
                // 输出待解码信元的Value,转换为大写并去除首尾空格
                System.out.println(sb.toString().toUpperCase().trim());
                break;
            } else {
                // 跳过当前信元
                index += (2 + length + 1);
            }
        }
    }
}

Python

# 定义一个函数,用于将给定的16进制字符串转换为整数
# length_str 是两个16进制字符拼接后的字符串(表示长度)
def get_length(length_str):
    return int(length_str, 16)  # 将16进制字符串转换为10进制整数# 主函数
def main():
    # 从用户输入中获取目标Tag,并去除首尾空白字符
    tag = input().strip()# 从用户输入中获取码流数据,并去除首尾空白字符
    line = input().strip()# 将码流数据按空格分割,存入hex_array数组中,每个元素是一个16进制字符串
    hex_array = line.split(" ")
​
    index = 0  # 初始化索引,用于遍历 hex_array# 使用while循环遍历整个hex_array
    while index < len(hex_array):
        # 解析当前信元的 Length 字段
        # Length 字段由两个字节组成,先拼接hex_array[index+2](高位)和hex_array[index+1](低位)
        # 再调用get_length函数将其转换为十进制整数
        length = get_length(hex_array[index + 2] + hex_array[index + 1])# 如果当前信元的Tag与输入的Tag匹配
        if hex_array[index] == tag:
            sb = []  # 定义一个空列表,用于存储匹配Tag后的Value部分# 从index+3位置开始(即第一个Value字节),提取length个字节的Value
            for i in range(index + 3, index + 3 + length):
                sb.append(hex_array[i])  # 将每个字节加入sb列表# 输出提取的Value部分,使用空格连接,并将输出转换为大写,去掉首尾多余空格
            print(" ".join(sb).upper().strip())
            break  # 找到匹配的Tag后,结束循环
        else:
            # 如果当前Tag不匹配,则跳过当前信元
            # 跳过的字节数为:1 个 Tag + 2 个 Length + length 个 Value
            index += (2 + length + 1)# 检查是否在直接运行脚本
if __name__ == "__main__":
    main()  # 调用主函数

JavaScript

// 引入 'readline' 模块,用于读取标准输入输出
const readline = require('readline');// 创建接口实例,用于处理输入输出
const rl = readline.createInterface({
  input: process.stdin,   // 标准输入流
  output: process.stdout  // 标准输出流
});// 首次监听 'line' 事件,获取用户输入的目标 Tag
rl.on('line', (tag) => {// 第二次监听 'line' 事件,获取码流数据
  rl.on('line', (line) => {
    // 将码流按空格分割,存入 hexArray 数组
    const hexArray = line.split(" ");
    
    let index = 0;  // 定义索引,用于遍历 hexArray// 使用循环遍历整个 hexArray
    while (index < hexArray.length) {
      // 解析 Length 字段。Length 由两个字节组成,先拼接后转为16进制整数
      const length = parseInt(hexArray[index + 2] + hexArray[index + 1], 16);// 如果当前的 Tag 和用户输入的 Tag 匹配
      if (hexArray[index] === tag) {
        const sb = [];  // 定义一个数组,用于存储 Value 部分
        
        // 将 Tag 后的 length 个字节的 Value 加入 sb 数组
        for (let i = index + 3; i < index + 3 + length; i++) {
          sb.push(hexArray[i]);
        }// 将 sb 数组中的 Value 转换为大写字符串并输出,去掉多余空格
        console.log(sb.join(" ").toUpperCase().trim());
        break;  // 找到目标 Tag 后,结束循环
      } else {
        // 如果 Tag 不匹配,跳过当前信元
        // 跳过的字节数为:1 个 Tag + 2 个 Length + length 个 Value
        index += (2 + length + 1);
      }
    }// 关闭 readline 接口,结束程序
    rl.close();
  });
});

C++

#include <iostream>
#include <vector>
using namespace std;int main() {
    string tag;  // 定义一个字符串变量存储要查找的Tag
    cin >> tag;  // 从输入中读取用户提供的Tag值
    
    string tmp;  // 临时字符串变量,用于存储每次输入的16进制字节
    vector<string> vec;  // 定义一个字符串向量,用于存储码流中按空格分隔的所有16进制字符串// 使用循环从标准输入中读取码流数据,直到遇到换行符为止
    while (cin >> tmp) {
        vec.push_back(tmp);  // 将每个16进制字节字符串存入向量
        if (cin.get() == '\n') break;  // 如果读取到换行符,停止输入
    }// 开始遍历向量vec,解析码流数据
    for (int i = 0; i < vec.size();) {
        string t = vec[i];  // 读取当前信元的Tag,即vec[i]// 解析Length字段(两个字节,小端序)
        // vec[i+1] 是低位字节,vec[i+2] 是高位字节
        // 计算方式为:低位 + 高位 * 16
        int len = stoi(vec[i + 1]) + 16 * stoi(vec[i + 2]);// 如果当前信元的Tag与目标Tag一致
        if (t == tag) {
            // 输出该Tag对应的Value部分
            // 从i + 3(第一个Value字节)开始,输出len个字节的Value
            for (int j = i + 3; j < i + 3 + len; j++) {
                cout << vec[j] << " ";  // 输出Value的每个字节,用空格分隔
            }
            cout << endl;  // 输出完毕后换行
            break;  // 找到匹配的Tag后,直接退出循环
        } else {
            // 如果当前Tag不匹配,则跳过该信元
            // 跳过Tag(1字节)+ Length(2字节)+ Value(len字节)
            i = i + 2 + len + 1;  // 移动i的位置,跳到下一个信元
        }
    }return 0;  // 程序结束
}

C语言

#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define MAX_LEN 50000  // 定义码流的最大长度int main() {
    char tag[3];  // 存储要查找的信元Tag,2个字符+1个结尾字符
    scanf("%s", tag);  // 输入要查找的Tag值char stream[MAX_LEN];  // 存储整条码流的输入
    getchar();  // 吸收掉换行符fgets(stream, MAX_LEN, stdin);  // 读取整条码流字符串,空格分隔// 定义一个数组来存储分割后的16进制字符串
    char *vec[MAX_LEN];
    int vec_size = 0;// 使用 strtok 函数将码流按空格分割
    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];  // 当前的Tag
        // 将长度部分解析为整数(小端序处理),vec[i+1]是低位,vec[i+2]是高位
        int len = atoi(vec[i + 1]) + 16 * atoi(vec[i + 2]);// 如果当前Tag与目标Tag相同
        if (strcmp(t, tag) == 0) {
            // 输出该信元的Value部分
            for (int j = i + 3; j < i + 3 + len; j++) {
                printf("%s ", vec[j]);
            }
            printf("\n");
            break;  // 找到后直接跳出循环
        } else {
            // 如果Tag不匹配,跳过当前信元,i += 2 (长度字节) + len (Value长度) + 1 (Tag字节)
            i = i + 2 + len + 1;
        }
    }return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

monday_CN

72小时打磨,值得1元认可

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值