編寫一個計算機程序用來計算一個文件的16位效驗和。最快速的方法是用一個32位的整數來存放這個和。記住要處理進位(例如,超過16位的那些位),把它們加到效驗和中。
要求:1)以命令行形式運行:check_sum infile
其中check_sum爲程序名,infile爲輸入數據文件名。
2)輸出:數據文件的效驗和
附:效驗和(checksum)
參見RFC1071 - Computing the Internet checksum
原理:把要發送的數據看成16比特的二進制整數序列,並計算他們的和。若數據字節長度爲奇數,則在數據尾部補一個字節的0以湊成偶數。
例子:16位效驗和計算,下圖表明一個小的字符串的16位效驗和的計算。
爲了計算效驗和,發送計算機把每對字符當成16位整數處理並計算效驗和。如果效驗和大於16位,那麼把進位一起加到最後的效驗和中。
版本一:沒有考慮出現中文格式的解決方法
#include<iostream>
#include<fstream>
#include<vector>
#define MAXVALE "0x10000"
using namespace std;
int charToInt(char c) {
int temp = (int)c;
if (temp >= (int)'0' && temp <= (int)'9') {
return (c - '0');
}
else if (temp >= (int)'A' && temp <= (int)'F') {
return (c - 'A') + 10;
}
}
char intToChar(int i) {
if (i >= 0 && i <= 9) return i + '0';
else if (i < 16) return (i - 10) + 'A';
}
int hexToInt(string hex) {
//例如0x1234
string temp = hex.substr(2, hex.length() - 2);
int result = 0;
for (int i = 0; i < temp.length(); i++) {
result *= 16;
result += charToInt(temp[i]);
}
return result;
}
string intToHex(int integer) {
string result = "";
while (integer > 0) {
result = intToChar(integer % 16) + result;
integer /= 16;
}
return "0x" + result;
}
void readFromText(string filePath);
void checksums(vector<string> vec) {
int data_sum = 0;
string temp = "";
for (int i = 0; i < vec.size(); i++) {
if (i % 2 == 0) {
temp = "0x"+vec[i];
}
else {
temp += vec[i];
data_sum += hexToInt(temp);
}
}
int maxValue = hexToInt(MAXVALE);
int carry = data_sum / maxValue;
int result = carry + data_sum % maxValue;
cout <<"\n校驗碼爲"<<intToHex(result) << endl;
}
int main(int args,char**argv) {
/*string filePath;
if (args > 1) {
filePath = argv[1];
}
else {
cout << "請輸入正確的格式:xx.exe filePath" << endl;
}*/
string filePath = "C:\\Users\\Lenovo\\Desktop\\1.txt";
readFromText(filePath);
}
void readFromText(string filePath) {
ifstream infile(filePath, ios::in);
if (!infile){
cerr << "File couldn't be open" << endl;
}
vector<string>vec;
char ch;
int time = 0;
while (infile.get(ch)) {
if (time % 5 == 0)
cout << endl;
time += 1;
cout << ch << " : ";
string hexNum = intToHex((int)ch);
cout << hexNum << "\t";
if (hexNum.length() == 1)//爲1或2
hexNum = "0"+hexNum.substr(2,hexNum.length()-2);
else
hexNum =hexNum.substr(2, hexNum.length() - 2);
vec.push_back( hexNum );
}
if (vec.size() % 2 == 1) {
vec.push_back("00");
}
infile.close();
cout << endl;
checksums(vec);
}
版本二:可以使用中文
考慮用二進制補碼來轉換
#include<iostream>
#include<fstream>
#include<vector>
#define MAXVALE "0x10000"
using namespace std;
int charToInt(char c) {
int temp = (int)c;
if (temp >= (int)'0' && temp <=(int)'9') {
return (c - '0');
}
else if (temp >= (int)'A' && temp <= (int)'F') {
return (c - 'A') + 10;
}
}
char intToChar(int i) {
if (i >= 0 && i <= 9) return i + '0';
else if (i < 16) return (i - 10) + 'A';
}
string intToBin(int integer) {//求的是補碼
string result = "";
int sign = 0;
if (integer < 0)
{
sign = 1;
integer *= -1;
}
while (integer > 0) {
result = intToChar(integer%2)+result;
integer >>= 1;
}
while ((result.size() % 8!=0 && result.size()>0)||result.size()==0)
result = '0' + result;
//從右往左數,第一個1左邊的數取反
string temp="";
if (sign==1 && integer< 128) {
for (int i = 7; i >= 0; i--) { //從右往左數
if (result[i] == '1') { //找到第一個1
temp = result[i] + temp;
for (int j = i-1; j >=0; j--) {//左邊所有數
if (result[j] == '0')
temp = '1' + temp;
else
temp = '0' + temp;
}
break;
}
else
temp = result[i] + temp;
}
result = temp;
}
result = "0B" + result;
return result;
}
int binToInt(string bin) {
int result=0;
bin = bin.substr(2, bin.length() - 2);
while ((bin.size() % 8 != 0 && bin.size() > 0) || bin.size() == 0){
bin = '0' + bin;
}
int sign = 0;
if (bin[0] == '1' && bin.size()==8) {
string temp = "";
sign = 1;
for (int i = bin.length()-1; i >= 0; i--) {//從右往左數
if (bin[i] == '1') {
temp = bin[i] + temp;
for (int j = i - 1; j >= 0; j--) {//左邊所有數
if (bin[j] == '0')
temp = '1' + temp;
else
temp = '0' + temp;
}
break;
}
else
temp = bin[i] + temp;
}
bin = temp;
}
for (int i = 0; i < bin.length(); i++) {
result = result<< 1;
result += (bin[i]-'0');
}
if (sign)
return -1 * result;
else
return result;
}
string binToHex(string bin) {
bin = bin.substr(2, bin.length() - 2);
//while (bin.length() < 8) {
while ((bin.size() % 8 != 0 && bin.size() > 0) || bin.size() == 0) {
bin = '0' + bin;
}
string hex="0x";
string temp = "0B";
int result = 0;
for (int i = 0;i< bin.length() ;i++ ) {
if (i % 4 == 3) {
temp = temp + bin[i];
result = binToInt(temp);
hex = hex + intToChar(result);
temp = "0B";
}
else
temp = temp + bin[i];
}
return hex;
}
string intToHex(int integer) {
string bin = intToBin(integer);
return binToHex(bin);
}
string hexToBin(string hex) {
string bin = "0B";
string temp="";
int integer = 0;
hex = hex.substr(2, hex.length() - 2);
for(int i=0;i<hex.length();i++){
integer = charToInt(hex[i]);
temp = intToBin(integer);//控制大於4位,在這裏截斷前面的
temp = temp.substr( temp.length() - 4,4);
bin = bin +temp;
}
return bin;
}
int hexToInt(string hex) {
string bin = hexToBin(hex);
return binToInt(bin);
}
void checksums(vector<string> vec);
void readFromText(string filePath) {
ifstream infile(filePath, ios::in);
if (!infile) {
cerr << "File couldn't be open" << endl;
}
vector<string>vec;
char ch;
cout << "文本讀取到內容爲";
int time = 0;
while (infile.get(ch)) {
if (time % 5 == 0)
cout << endl;
time += 1;
cout << ch << " : ";
string hexNum = intToHex((int)ch);
cout << hexNum << " " ;
if (hexNum.length() == 1)
hexNum = "0" + hexNum.substr(2, hexNum.length() - 2);
else
hexNum = hexNum.substr(2, hexNum.length() - 2);
vec.push_back(hexNum);
}
if (vec.size() % 2 == 1) {
vec.push_back("00");
}
infile.close();
checksums(vec);
}
void checksums(vector<string> vec) {
int data_sum = 0;
string temp = "";
cout << "\n16位數值如下:" << endl;
for (int i = 0; i < vec.size(); i++) {
if (i % 2 == 0) {
temp = "0x" + vec[i];
}
else {
temp += vec[i];
cout << temp << " ";
data_sum += hexToInt(temp);
}
}
int maxValue = hexToInt(MAXVALE);
int carry = data_sum / maxValue;
int result = carry + data_sum % maxValue;
cout << "\n校驗碼爲" << intToHex(result) << endl;
}
int main(int args, char** argv) {
string filePath;
/*if (args > 1) {
filePath = argv[1];
}
else {
cout << "請輸入正確的格式:xx.exe filePath" << endl;
}*/
filePath = "C:\\Users\\Lenovo\\Desktop\\1.txt";
readFromText(filePath);
}