链路层的编码研究(1)二进制码的打印

在计通网的课程中,学习到了链路层的各种编码方式。希望用C++来实现。如果是用字符串、容器之类的方法实现的话,会占用很大的存储空间,虽然实现编码会很简单,但是失去了很多对于底层数据类型操作的乐趣。因此,我准备使用unsigned char类型来保存数据,将各种数据类型的内存现场保存下来,然后打印输出,得到真实的位保存。

因此,我首先使用了一个DataReader的类来实现各种数据类型的读入,然后通过所有的编码方法的总的类:Coder,来实现编码与打印。关键技术在于C++提供的reinterpret_cast关键字,可以使用重新解释的方式来轻松得到数据的内存现场的保存。

DataReader类中,有三个属性,storage指向数据的内存,size代表数据类型的大小,length代表数据的个数,即存入数组的长度。

以下是DataReader的代码:

// binaryprinter.h

#ifndef BINARYPRINTER_H
#define BINARYPRINTER_H

class Coder;
class DataReader
{
	unsigned char* storage;
	int size;
	int length;
public:
	DataReader() : storage(0), size(0), length(0) {}
	DataReader(unsigned char* print, int len)
	{
		storage = print;
		size = sizeof(print);
		length = len;
	}
	DataReader(unsigned char print)
	{
		storage = new unsigned char(print);
		size = sizeof(unsigned char);
		length = 1;
	}

	DataReader(int print)
	{
		storage = reinterpret_cast<unsigned char*>(new int(print));
		size = sizeof(int);
		length = 1;
	}
	DataReader(int* print, int len) {
		storage = reinterpret_cast<unsigned char*>(print);
		size = sizeof(print);
		length = len;
	}
	
	DataReader(char* print, int len) {
		storage = reinterpret_cast<unsigned char*>(print);
		size = sizeof(print);
		length = len;
	}
	DataReader(char print)
	{
		storage = reinterpret_cast<unsigned char*>(new char(print));
		size = sizeof(char);
		length = 1;
	}

	DataReader(short print)
	{
		storage = reinterpret_cast<unsigned char*>(new short(print));
		size = sizeof(short);
		length = 1;
	}
	DataReader(short* print, int len)
	{
		storage = reinterpret_cast<unsigned char*>(print);
		size = sizeof(print);
		length = len;
	}

	DataReader(unsigned short print)
	{
		storage = reinterpret_cast<unsigned char*>(new unsigned short(print));
		size = sizeof(unsigned short);
		length = 1;
	}
	DataReader(unsigned short* print, int len)
	{
		storage = reinterpret_cast<unsigned char*>(print);
		size = sizeof(print);
		length = len;
	}

	DataReader(unsigned int* print, int len) {
		storage = reinterpret_cast<unsigned char*>(print);
		size = sizeof(print);
		length = len;
	}
	DataReader(unsigned int print)
	{
		storage = reinterpret_cast<unsigned char*>(new unsigned int(print));
		size = sizeof(unsigned int);
		length = 1;
	}

	DataReader(float* print, int len) {
		storage = reinterpret_cast<unsigned char*>(print);
		size = sizeof(print);
		length = len;
	}
	DataReader(float print)
	{
		storage = reinterpret_cast<unsigned char*>(new float(print));
		size = sizeof(float);
		length = 1;
	}

	DataReader(double* print, int len) {
		storage = reinterpret_cast<unsigned char*>(print);
		size = sizeof(print);
		length = len;
	}
	DataReader(double print) : size(sizeof(double)) {
		storage = reinterpret_cast<unsigned char*>(new double(print));
		length = 1;
	}

	DataReader(long* print, int len) {
		storage = reinterpret_cast<unsigned char*>(print);
		size = sizeof(print);
		length = len;
	}
	DataReader(long print) : size(sizeof(long)) {
		storage = reinterpret_cast<unsigned char*>(new long(print));
		length = 1;
	}

	DataReader(unsigned long* print, int len) {
		storage = reinterpret_cast<unsigned char*>(print);
		size = sizeof(print);
		length = len;
	}
	DataReader(unsigned long print) : size(sizeof(unsigned long)) {
		storage = reinterpret_cast<unsigned char*>(new unsigned long(print));
		length = 1;
	}

	void setStorage(unsigned char* print, int len)
	{
		size = sizeof(print);
		length = len;
		if (storage)
			delete [] storage;
		storage = print;
	}

	void setStorage(unsigned char print)
	{
		size = sizeof(print);
		if (storage)
			delete [] storage;
		storage = new unsigned char(print);
		length = 1;
	}

	void setStorage(char print)
	{
		if (storage)
			delete [] storage;
		size = sizeof(char);
		length = 1;
		storage = reinterpret_cast<unsigned char*>(new char(print));
	}
	void setStorage(char* print, int len)
	{
		if (storage)
			delete [] storage;
		size = sizeof(char);
		storage = reinterpret_cast<unsigned char*>(print);
		length = len;
	}

	void setStorage(int print)
	{
		if (storage)
			delete [] storage;
		size = sizeof(print);
		length = 1;
		storage = reinterpret_cast<unsigned char*>(new int(print));
	}
	void setStorage(int* print, int len)
	{
		if (storage)
			delete [] storage;
		size = sizeof(print);
		length = len;
		storage = reinterpret_cast<unsigned char*>(print);
	}

	void setStorage(unsigned int print)
	{
		if (storage)
			delete [] storage;
		size = sizeof(print);
		length = 1;
		storage = reinterpret_cast<unsigned char*>(new unsigned int(print));
	}
	void setStorage(unsigned int* print, int len)
	{
		if (storage)
			delete storage;
		size = sizeof(print);
		length = len;
		storage = reinterpret_cast<unsigned char*>(print);
	}

	void setStorage(float print)
	{
		if (storage)
			delete [] storage;
		size = sizeof(print);
		length = 1;
		storage = reinterpret_cast<unsigned char*>(new float(print));
	}
	void setStorage(float* print, int len)
	{
		if (storage)
			delete []storage;
		size = sizeof(print);
		length = len;
		storage = reinterpret_cast<unsigned char*>(print);
	}

	void setStorage(double print)
	{
		if (storage)
			delete [] storage;
		size = sizeof(print);
		length = 1;
		storage = reinterpret_cast<unsigned char*>(new double(print));
	}
	void setStorage(double* print, int len)
	{
		if (storage)
			delete [] storage;
		size = sizeof(print);
		length = len;
		storage = reinterpret_cast<unsigned char*>(print);
	}

	void setStorage(long print)
	{
		if (storage)
			delete [] storage;
		size = sizeof(print);
		length = 1;
		storage = reinterpret_cast<unsigned char*>(new long(print));
	}
	void setStorage(long* print, int len)
	{
		if (storage)
			delete [] storage;
		size = sizeof(print);
		length = len;
		storage = reinterpret_cast<unsigned char*>(print);
	}

	void setStorage(unsigned long print)
	{
		if (storage)
			delete [] storage;
		size = sizeof(print);
		length = 1;
		storage = reinterpret_cast<unsigned char*>(new unsigned long(print));
	}
	void setStorage(unsigned long* print, int len)
	{
		if (storage)
			delete [] storage;
		size = sizeof(print);
		length = len;
		storage = reinterpret_cast<unsigned char*>(print);
	}

	void setStorage(short print)
	{
		if (storage)
			delete [] storage;
		size = sizeof(print);
		length = 1;
		storage = reinterpret_cast<unsigned char*>(new short(print));
	}
	void setStorage(short* print, int len)
	{
		if (storage)
			delete [] storage;
		size = sizeof(print);
		length = len;
		storage = reinterpret_cast<unsigned char*>(print);
	}

	void setStorage(unsigned short print)
	{
		if (storage)
			delete [] storage;
		size = sizeof(print);
		length = 1;
		storage = reinterpret_cast<unsigned char*>(new unsigned short(print));
	}
	void setStorage(unsigned short* print, int len)
	{
		if (storage)
			delete [] storage;
		size = sizeof(print);
		length = len;
		storage = reinterpret_cast<unsigned char*>(print);
	}
	
	friend class Coder;
};

#endif

而Coder类中,由于编码会改变数据的长度,因此另设prtlen属性,代表现有内存的长度。由于数组数据在内存中的存储与逻辑上的顺序不同,因此在打印时使用直接的内存打印。在注释中给出按逻辑打印的方法。

以下是Coder的代码:

// coder.h

#ifndef CODER_H
#define CODER_H

#include "datareader.h"
#include <iostream>
#include <vector>

class Coder
{
protected:
	unsigned char* storage;
	int size;
	int length;
	DataReader& data;
	int prtlen;
public:
	Coder(DataReader* dr) : data(*dr)
	{
		storage = data.storage;
		size = data.size;
		length = data.length;
		prtlen = size * length;
	}
	void update()
	{
		storage = data.storage;
		size = data.size;
		length = data.length;
	}
	DataReader& getDataReader()
	{
		return data;
	}
	// This print function show how to show the magic memory.
	// But I will use the real memory method,
	// because it's easy to code and decode.
	/*std::ostream& print(std::ostream& out)
	{
		for (int i = 0; i < length; i++)
			for (int j = size - 1; j >= 0; j--)
				for(int k = 7; k >= 0; k--)
					if (storage[i * size + j] & (1 << k))
						out << 1;
					else
						out << 0;
		return out;
	}*/
	std::ostream& print(std::ostream& out)
	{
		for (int i = 0; i < prtlen; i++)
			for (int j = 7; j >= 0; j--)
				if (storage[i] & (1 << j))
					out << 1;
				else
					out << 0;
		return out;
	}
	void print()
	{
		print(std::cout);
	}
	
	virtual void code() {}
	//virtual void decode() = 0;
};

std::ostream& operator<<(std::ostream& out, Coder& coder) {
		return coder.print(out);
}

#endif

现在,使用Coder类就可以实现多种数据类型以及对应数组的二进制输出了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值