校验和的计算方法

实验要求

编写一个计算机程序用来计算一个文件的16位效验和。最快速的方法是用一个32位的整数来存放这个和。记住要处理进位(例如,超过16位的那些位),把它们加到效验和中。

要求

1)以命令行形式运行:check_sum infile

其中check_sum为程序名,infile为输入数据文件名。

2)输出:数据文件的效验和

附:效验和(checksum)

参见RFC1071 - Computing the Internet checksum

原理:把要发送的数据看成16比特的二进制整数序列,并计算他们的和。若数据字节长度为奇数,则在数据尾部补一个字节的0以凑成偶数。

例子:16位效验和计算,下图表明一个小的字符串的16位效验和的计算。

为了计算效验和,发送计算机把每对字符当成16位整数处理并计算效验和。如果效验和大于16位,那么把进位一起加到最后的效验和中。
HelloWorld

思路

这里计算校验和的方法是,先把文件中的所有字符都读成一整个字符串。把每个字符都转换成十进制的ASCII码。因为是把两个字符合成一个16比特的整数,所以这里我把高位和高位相加,低位和低位相加,如果字符的个数为奇数,那么最后一个字符后面还要补上一个字节的0以凑成偶数。然后处理低位相加的进位和高位相加的进位,这里要循环处理高位的进位,因为把高位的进位加到低位上可能还会产生进位。处理的结果还是十进制,转换成十六进制即可。

如果要以命令行形式运行:check_sum infile。前面的check_sum是程序运行产生的exe可执行文件,后面的infile则是被读取文件的路径。另外,程序里的main函数还要加上参数,int main(int argc, char* argv[]),其中命令行的infile作为数据传给argv[1],程序里用一个变量保存argv[1]作为路径。

代码

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
using namespace  std;

#define path "test.txt"

// 十进制转换为十六进制
string decToHex(int high, int low){
	const std::string hex = "0123456789ABCDEF";
	stringstream ss;
	ss << hex[high >> 4] << hex[high & 0xf];
	ss << hex[low >> 4] << hex[low & 0xf];
	return ss.str();
}

int main(int argc, char* argv[]) {
	string str, tmp = "";
	//path = argv[1];
	ifstream inf(path, ios::in);
	vector<int> l, r;
	while (getline(inf, tmp)) {
		str += tmp;
	}
	cout << str << endl;

	int size = str.size();
	int len = 0;
	cout << "16进制:";
	for (int i = 0; i < size - 1; i += 2) {
		l.push_back((int)str[i]);
		r.push_back((int)str[i + 1]);
		cout << "0x" << decToHex(l[len], r[len]) << " ";
		len++;
	}
	if (size % 2 == 1) {
		l.push_back((int)str[size - 1]);
		r.push_back(0);
		cout << "0x" << decToHex(l[len], r[len]) << " ";
		len++;
	}
	cout << endl;
	// 低位加低位
	int low = 0, t = 0;  // t是进位
	for (int i = 0; i < len; i++) {
		low += r[i];
		if (low > 255) {
			t += (low / 256);
			low %= 256;
		}
	}
	// 高位加高位
	int high = t, t2 = 0;  // t2也是进位
	for (int i = 0; i < len; i++) {
		high += l[i];
		if (high > 255) {
			t2 += (high / 256);
			high %= 256;
		}
	}
	// 处理进位
	while (t2 != 0) {
		low += t2;
		t = 0;
		t2 = 0;
		if (low > 255) {
			t = low / 256;
			low %= 256;
		}
		high += t;
		if (high > 255) {
			t2 = high / 256;
			high %= 256;
		}
	}
	
	cout << "校验和:" << decToHex(high, low) << endl;
	
	inf.close();
	return 0;
}

Snipaste_2019-12-02_22-03-58
Snipaste_2019-12-02_22-04-38

发布了100 篇原创文章 · 获赞 34 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_42780289/article/details/103358272