實驗要求
編寫一個計算機程序用來計算一個文件的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;
}