实验要求
编写一个计算机程序用来计算一个文件的16位效验和。最快速的方法是用一个32位的整数来存放这个和。记住要处理进位(例如,超过16位的那些位),把它们加到效验和中。
要求:
1)以命令行形式运行:check_sum infile
其中check_sum为程序名,infile为输入数据文件名。
2)输出:数据文件的效验和
附:效验和(checksum)
参见RFC1071 - Computing the Internet checksum
原理:把要发送的数据看成16比特的二进制整数序列,并计算他们的和。若数据字节长度为奇数,则在数据尾部补一个字节的0以凑成偶数。
例子:16位效验和计算,下图表明一个小的字符串的16位效验和的计算。
为了计算效验和,发送计算机把每对字符当成16位整数处理并计算效验和。如果效验和大于16位,那么把进位一起加到最后的效验和中。
思路
这里计算校验和的方法是,先把文件中的所有字符都读成一整个字符串。把每个字符都转换成十进制的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;
}