(B卷,100分)- TLV解码(Java & JS & Python & C)

题目描述

TLV编码是按[Tag Length Value]格式进行编码的,一段码流中的信元用Tag标识,Tag在码流中唯一不重复,Length表示信元Value的长度,Value表示信元的值。

码流以某信元的Tag开头,Tag固定占一个字节,Length固定占两个字节,字节序为小端序

现给定TLV格式编码的码流,以及需要解码的信元Tag,请输出该信元的Value。

输入码流的16进制字符中,不包括小写字母,且要求输出的16进制字符串中也不要包含小写字母;码流字符串的最大长度不超过50000个字节。

输入描述

  • 输入的第一行为一个字符串,表示待解码信元的Tag;
  • 输入的第二行为一个字符串,表示待解码的16进制码流,字节之间用空格分隔。

输出描述

  • 输出一个字符串,表示待解码信元以16进制表示的Value。

用例

输入 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
输出 32 33
说明

需要解析的信元的Tag是31,

从码流的起始处开始匹配,

第一个信元的Tag是32,信元长度为1(01 00,小端序表示为1);

第二个信元的Tag是90,其长度为2;

第三个信元的Tag是30,其长度为3;

第四个信元的Tag是31,其长度为2(02 00),

所以返回长度后面的两个字节即可,即32 33。

题目解析

本题题目可能比较难理解,但是大概意思如下:

第二行输入的码流,是由多个信元组成的,每个信元又是由tag、len、val组成

其中tag占一个字节,len占两个字节,而val占的的字节数由len决定,因此上面用例的第二行输入如下图:

可能这样大家就一目了然了吧。 

现在要找tag为31信元的val,从上图可以看出val为32 33

JavaScript算法源码

/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

const lines = [];
rl.on("line", (line) => {
  lines.push(line);

  if (lines.length === 2) {
    // 待解码信元的Tag
    const tag = lines[0];

    // 待解码的16进制码流
    const stream = lines[1].split(" ");

    console.log(getResult(stream, tag));

    lines.length = 0;
  }
});

function getResult(stream, find) {
  // 这里反转数组是为了后面避免shift操作,转而使用pop操作,pop的性能更优一点
  stream.reverse();

  while (stream.length) {
    const tag = stream.pop();

    const len = parseInt(
      // 由于是小端序,因此需要反转
      [stream.pop(), stream.pop(), "0x"].reverse().join(""),
      16
    );

    const val = [];
    for (let i = 0; i < len; i++) {
      val.push(stream.pop());
    }

    if (tag === find) {
      return val.join(" ");
    }
  }
}

Java算法源码

import java.util.ArrayList;
import java.util.Scanner;
import java.util.StringJoiner;

public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    String target = sc.nextLine();
    String[] stream = sc.nextLine().split(" ");

    System.out.println(getResult(stream, target));
  }

  public static String getResult(String[] stream, String target) {
    int i = 0;

    while (i < stream.length) {
      String tag = stream[i++];

      String tmp1 = stream[i++];
      String tmp2 = stream[i++];

      int len = Integer.parseInt(tmp2 + tmp1, 16);

      ArrayList<String> val = new ArrayList<>();
      for (int j = 0; j < len; j++) {
        val.add(stream[i++]);
      }

      if (tag.equals(target)) {
        StringJoiner sj = new StringJoiner(" ");
        for (String s : val) sj.add(s);
        return sj.toString();
      }
    }

    return null;
  }
}

Python算法源码

# 输入获取
target = input()
stream = input().split()


# 算法入口
def getResult():
    stream.reverse()

    while len(stream) > 0:
        # 这里反转数组是为了后面避免shift操作,转而使用pop操作,pop的性能更优一点
        tag = stream.pop()

        tmp = [stream.pop(), stream.pop(), "0x"]
        #  由于是小端序,因此需要反转
        tmp.reverse()

        long = int("".join(tmp), 16)

        val = []
        for i in range(long):
            val.append(stream.pop())

        if tag == target:
            return " ".join(val)


# 算法调用
print(getResult())

C算法源码

#include <stdio.h>
#include <string.h>

#define MAX_SIZE 100000

int main() {
    char target[4];
    gets(target);

    char stream[MAX_SIZE][4];
    int stream_size = 0;
    while(scanf("%s", stream[stream_size++])) {
        if(getchar() != ' ') break;
    }

    int i = 0;
    while(i < stream_size) {
        char* tag = stream[i++];

        char* tmp1 = stream[i++];
        char* tmp2 = stream[i++];

        char tmp[5] = {''};
        strcat(tmp, tmp2);
        strcat(tmp, tmp1);

        int len;
        sscanf(tmp, "%x", &len);


        char res[len * 5];
        memset(res, '', len*5);

        for(int j = 0; j < len; j++) {
            strcat(res, stream[i++]);
            if(j < len - 1) {
                strcat(res, " ");
            }
        }

        if(strcmp(tag, target) == 0) {
            puts(res);
            return 0;
        }
    }

    return 0;
}

免责声明:

1、IT资源小站为非营利性网站,全站所有资料仅供网友个人学习使用,禁止商用
2、本站所有文档、视频、书籍等资料均由网友分享,本站只负责收集不承担任何技术及版权问题
3、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除下载链接并致以最深的歉意
4、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
5、一经注册为本站会员,一律视为同意网站规定,本站管理员及版主有权禁止违规用户
6、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和IT资源小站的同意
7、IT资源小站管理员和版主有权不事先通知发贴者而删除本文

0

评论0

站点公告

没有账号?注册  忘记密码?