题目描述
校验和(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
-
输入报文的字节长度为11。
-
补齐为4的倍数后为61 62 63 64 32 30 31 32 4C 61 62 FF,倍数为3。
-
每次取4个字节,第一次取得的 0x61626364,与第二次取得的 0x32303132,异或运算结果为 0x53525256,运算结果继续与第三次取得的 0x4C6162FF 进行异或运算。
-
最后得到十六进制数值 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