在计通网的课程中,学习到了链路层的各种编码方式。希望用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类就可以实现多种数据类型以及对应数组的二进制输出了