编写一个计算机程序用来计算一个文件的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);
}