【HUAWEI OJ 题库】简易校验和算法

题目描述
校验和(Checksum)常用在验证一段网络报文或一个文件是否被篡改。假设网络报文每个字节用2位十六进制数字表达,某种校验和的计算规则如下:

  • 若待校验内容的字节长度不是4的倍数,则在尾部使用值为 0xFF 的字节补齐为4的倍数(最多补充3个字节)。
  • 假设补齐后的字节长度除以4,得到一个正整数 n
  • 若 n 等于 1,内容即为校验和;
  • 若 n 大于 1,首先取开头 4 个字节与第5-8字节进行异或运算,然后运算结果与随后的 4 个字节继续进行异或运算,直至结束,最后的结果即为校验和。
  • 现给定一段网络报文,请计算并输出其校验和。

解答要求

时间限制:1000ms, 内存限制:256MB

输入

十六进制字符串表示的、合法的网络报文,每2个字符(输入仅为[0-9A-F])表示一个字节,字节之间以单空格分隔;字符串首尾无空格,长度范围:[2, 200]

输出

十六进制字符串形式的校验和, 格式如0000000A,说明:

  • 固定8个字符长度(不足8个时,使用前导0补充);
  • 字母使用大写字母 (A~F)。

样例

输入样例 1

61 62 63 64 32 30 31 32 4C 61 62

输出样例 1

1F3330A9

提示样例 1

  1. 输入报文的字节长度为11。

  2. 补齐为4的倍数后为61 62 63 64 32 30 31 32 4C 61 62 FF,倍数为3。

  3. 每次取4个字节,第一次取得的 0x61626364,与第二次取得的 0x32303132,异或运算结果为 0x53525256,运算结果继续与第三次取得的 0x4C6162FF 进行异或运算。

  4. 最后得到十六进制数值 0x1F3330A9 ,结果输出为字符串1F3330A9,注意:不用在前面增加0x

输入样例 2

41

输出样例 2

41FFFFFF

提示样例 2

输入报文的字节长度为1,补齐后为 41FFFFFF(注意最多补3个FF),即得到校验和,输出为 41FFFFFF。

输入样例 3

68 75 61 77 65 69

输出样例 3

0D1C9E88

提示样例 3

注意加前导0

提示

异或运算是对两个运算元的一种运算类型,运算法则相当于不带进位的二进制加法,运算符为 ^ 。例如 3 ^ 5 = 6 。

编码实现(Java)

    public static void main(String[] args) {
        String inputStr = "61 62 63 64 32 30 31 32 4C 61 62";
        String result = simpleCheckSum(inputStr);
        System.out.println(result);
    }

    private static String simpleCheckSum(String inputStr) {
        // 将输入的十六进制字符串转换为字节数组
        String[] hexBytes = inputStr.split(" ");
        byte[] byteArray = new byte[hexBytes.length];
        for (int i = 0; i < hexBytes.length; i++) {
            byteArray[i] = (byte) Integer.parseInt(hexBytes[i], 16);
        }

        // 计算补齐字节数
        int paddingBytes = 4 - byteArray.length % 4;
        if (paddingBytes < 4) {
            // 在尾部补齐字节
            byte[] paddedArray = new byte[byteArray.length + paddingBytes];
            System.arraycopy(byteArray, 0, paddedArray, 0, byteArray.length);
            Arrays.fill(paddedArray, byteArray.length, paddedArray.length, (byte) 0xFF);
            byteArray = paddedArray;
        }

        // 初始化校验和为0
        int checksum = 0;

        // 每4个字节进行一次异或运算
        for (int i = 0; i < byteArray.length; i += 4) {
            // 取出4个字节
            byte[] chunk = Arrays.copyOfRange(byteArray, i, i + 4);
            // 将4个字节转换为整数
            int value = ByteBuffer.wrap(chunk).getInt();
            // 异或运算
            checksum ^= value;
        }

        // 将结果格式化为8位的十六进制字符串
        return String.format("%08X", checksum);
    }

输出结果

1F3330A9

Process finished with exit code 0
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值