C++ 编写一个计算机程序用来计算一个文件的 16 位效验和 详解。

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

要求:
1)以命令行形式运行:check_sum infile 其中 check_sum 为程序名,infile 为输入数据文件名。

2)输出:数据文件的效验和 附:效验和(checksum) 参见 RFC1071 - Computing the Internet checksum

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

✓ 例子:16 位效验和计算,下图表明一个小的字符串的 16 位效验和的计算。 为了计算效验和,发送计算机把每对字符当成 16 位整数处理并计算效验和。如果效验 和大于 16 位,那么把进位一起加到最后的效验和中。

在这里插入图片描述
思路:
1.十六位校验和也就是用十六位二进制数据来进行校验,而二进制数据太长了,为了美观换算成四位十六进制,一个字符对应的ASCLL码换算成十六进制也就是两位,所以需要两个字符作为一组数据。

先自定义一串字符串,计算其校验和。先把字符分成每两个一组,如果字符数量是奇数,那么最后一个先让它单独一组。(空格也算字符)

2.每两个字符作为一组数据,先把两个字符所对应的ascll码找出来,然后转换成十六进制,前一个字符对应的ASCLL码作为数据的高位,后一个字符对应的ASCLL码作为数据的低位。(因为是16进制,所以高位的数据需要在原ASCLL码的基础上乘16^2。)

像上面的H,ASCLL码对应的十进制是72,十六进制为48;e对应的ASCLL码的十进制是101,十六进制为65。

获取字符的ASCLL码可以这样:

char a[20]={"Hello world."};
int b=(int)a[0];//获取a[0]对应字符的ASCLL

3.遇到字符数是奇数的情况,在数据尾部补一个字节的0来凑成偶数。事实上到了最后一个数据的时候,如果它刚好是奇数,记得要把这个字符对应的数据变成高位,也就是ASCLL码乘16^2。

4.把上面得到的全部的四位(四位十六进制也就是十六位二进制)十六进制的数据相加起来,因为校验和的位数确定了,所有如果有进位,就把进位的数据加到低位。

假如最后相加得到的十六进制数据为:1A356,可以看出进位为1,然后把1加到后四位的低位形成新的数据A357就是所得的校验和。

事实上数据可以在最后输出校验和的时候再换算成十六进制,在前面计算的时候只要你把数据当成十六进制来处理高低位以及最后的进位就可以了。

源码:

#include<fstream>
#include<iostream>
using namespace std;
void main() 
{
	char a[20] = { "Hello world." };
	ofstream out("f:\\infile.txt");
	out << a;
	out.close();
	char b[20] = { 0};
	ifstream in("f:\\infile.txt");
	int i = 0;
	while (in) 
	{//循环获取文件里的内容
		
		b[i] = in.get();
		
		if (b[i] == -1)//结束标志,并把获得的-1替换成0
		{
			b[i] = 0;
		}
		i++;
	}
	in.close();
	cout << "校验序列为:";
	cout << b<<endl;
	int j = 0;
	while (1)//循环判断有多少个字符
	{
		if (b[j] == '\0')
		{
			break;
		}
		j++;
	}
	
	cout << "字符数为:";
	cout << j<<endl;
	int c[20] = { 0 };//放ASCLL
	int t=0;
	
		int k=0;
		while (1)
		{
			if (k == j)//直接用条件判断,把字符数为1奇数的情况也考虑进去
			{
				break;
			}
			if (k % 2 == 0)//每两组的前面一位
			{
				c[k] = ((int)b[k]) * 16 * 16;//按16进制左移两位
				k++;
			}
			else//后面一位
			{
				c[k] = (int)b[k];
				k++;
			}
		}
		int x=0;
		while (x < j)
		{
			t = t + c[x];
			x++;
		}
		int a1, a2;
		a1 = t / (16^4);//取高位的进位
		a2 = t % (16^4);//取除高位外的数
		t = a1 + a2;//将进位加到低位
		cout << "校验和为:";
		cout << std::hex<< t;//转换成16进制
}

文件流按字节获取文件中的字符的时候,in.get()的结束标志是-1,但是当你知道是结束符的时候程序已经进入了循环了,会把-1赋给数组,这样会导致字符串无效。所有需要一个判断语句。

最后的最后,源码主要是给大家参考大概要怎么做的,具体程序还是大家自己想,毕竟懂了要干嘛之后,这个实验就很简单了。

如果哪里有错误的地方欢迎大家在评论区指出!

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值