20-Qt中数据通信与数据保存用到的强制类型转换(C++类型强制转换)

在软件开发中经常会用到一些类型转换,本文所列出的类型转换是在做一个项目中所使用到的所有类型转换。在项目中把这几个类型转换单独封装成了通用类。以下分别介绍。

一、ByteUtil

在电脑软件和硬件设备通信的开发中,经常用到这个类。在这类软件中需要把电脑软件代码所使用的数据类型转换为与硬件通信协议所规定的格式。(通信协议里面的格式一般按照byte位类做设计)。

使用情形举例:
定义“typedef unsigned char byte;”。在代码中以byte为基本单位,生成了通信协议所规定的数据格式的数据(数组或结构体)。但是在所有开发平台上发送数据的write函数所使用的参数都是“char*”。而要发送的数据类型是“byte*”。因此这里需要类型转换。避免报错或报警告。注意:char 和 unsigned char 在c++语言中是两个不同定义的基础数据类型。因此相互之间不能直接赋值。 这里转换类型后能正确使用且完成通信,是因为char和byte 都是8bit的数据类型。

类的代码如下:
byteutil.h

#ifndef BYTEUTIL_H
#define BYTEUTIL_H

typedef unsigned char byte;

namespace MyUtil {

class ByteUtil
{
private:
	ByteUtil();

public:
	static char Byte2Char(const byte byte);
	static byte Char2Byte(const char ch);
	
	static char Int2Char(const int value);//only last 8bit of int is saved
	static int Char2Int(const char ch);
	
	static void ByteArray2CharArray(const byte * src, char *dst, int len);
	static void CharArray2ByteArray(const char * src, byte *dst, int len);
};
} //namespace MyUtil

#endif // BYTEUTIL_H

byteutil.cpp

#include "byteutil.h"

namespace MyUtil {

ByteUtil::ByteUtil()
{

}

char ByteUtil::Byte2Char(const byte byte) {
	char ret = 0x00;
	ret = ret | byte;
	return ret;
}

byte ByteUtil::Char2Byte(const char ch) {
	byte by = 0x00;
	by = static_cast<byte>(by | ch);
	return by;
}

//only last 8bit of int is saved
char ByteUtil::Int2Char(const int value) {
	return Byte2Char(static_cast<unsigned char>(value));
}

int ByteUtil::Char2Int(const char ch) {
	byte t = Char2Byte(ch);
	return static_cast<int>(t);
}

void ByteUtil::ByteArray2CharArray(const byte * src, char *dst, int len) {
	for (int a = 0; a < len; a++) {
		dst[a] = Byte2Char(src[a]);
	}
}

void ByteUtil::CharArray2ByteArray(const char * src, byte *dst, int len) {
	for (int a = 0; a < len; a++) {
		dst[a] = Char2Byte(src[a]);
	}
}

} //namespace MyUtil

二、StringUtil

在软件开发中,会需要做”QString”和“char*”的相互类型转化。以及把字符串转换成16进制字符串来显示。转换类的代码如下:
stringutil.h

#ifndef STRINGUTIL_H
#define STRINGUTIL_H

#include <QString>

namespace MyUtil {

class StringUtil
{
public:
	StringUtil();
	static char* QString2CharStr(QString &str);
	static char ConvertHexChar(char ch);
	static void StringToHex(QString str, QByteArray &senddata);
};

} //namespace MyUtil

#endif // STRINGUTIL_H

stringutil.cpp

#include "stringutil.h"

namespace MyUtil {

StringUtil::StringUtil()
{

}

char* StringUtil::QString2CharStr(QString &str) {
	QByteArray sr = str.toLocal8Bit();
	int len = sr.length();
	char* filename = new char[len+2];
	filename[len] = filename[len+1] = 0;
	strcpy(filename,sr.data());
	return filename;
}

char StringUtil::ConvertHexChar(char ch) {
	if((ch >= '0') && (ch <= '9'))
	  return ch-0x30;
	else if((ch >= 'A') && (ch <= 'F'))
	  return ch-'A'+10;
	else if((ch >= 'a') && (ch <= 'f'))
	  return ch-'a'+10;
	else return (-1);
}

void StringUtil::StringToHex(QString str, QByteArray &senddata) {
	int hexdata,lowhexdata;
	int hexdatalen = 0;
	int len = str.length();
	senddata.resize(len/2);
	char lstr,hstr;
	for(int i=0; i<len; )
	{
		//char lstr,
		hstr=str[i].toLatin1();
		if(hstr == ' ')
		{
		 i++;
		 continue;
		}
		i++;
		if(i >= len)
			break;
		lstr = str[i].toLatin1();
		hexdata = ConvertHexChar(hstr);
		lowhexdata = ConvertHexChar(lstr);
		if((hexdata == 16) || (lowhexdata == 16))
			break;
		else
			hexdata = hexdata*16+lowhexdata;
		i++;
		senddata[hexdatalen] = static_cast<char>(hexdata);
		hexdatalen++;
	}
	senddata.resize(hexdatalen);
}

} //namespace MyUtil

三、TypeConverter(Struct2Byte <-> Byte2Struct)

在pc软件开发中,有的软件会要求可以保存和读取工程文件,或其他文件。这个时候需要把你软件内以设计好的数据结构保存的数据转换成文件储存的格式。并写入文件中。

这里使用的情形是保存和读取二进制文件。如果是纯粹的文本文件保存和读取就不会涉及到数据类型的转换。

那么储存和读取二进制文件为啥要进行类型转换?
答:软件运行中对处理的数据,都要设计特定的数据结构来储存。在面向对象语言开发中,一般会使用一个类来储存这些数据。比如:
软件要使用二进制文件记录一条由多个彩色点组成的任意曲线。所用的数据结构可能如下:

class ColorPoint {
	QColor color;
	QPoint point;
};

class ColorLine {
	QString name;
	QList<ColorPoint> point_list;
};

要把如上数据结构储存在二进制文件中怎么做呢?
注意保存工程等二进制文件和“序列化与反序列化”的区别。不应该把序列化的二进制数据当成工程文件来储存(虽然可以暂时达到储存工程文件的效果)。

正确储存工程文件的方法:
依照类对象定义一个对应的结构体,且结构体内只使用基本数据类型。比如如上两个类对应的结构体应该如下:

#pragma pack(1)
struct ColorPoint_Struct {
	uchar color_r;
	uchar color_g;
	uchar color_b;
	int pos_x;
	int pos_y;
};

#pragma pack(1)
struct ColorLine_Struct {
	char name[40];
	int color_point_list_length;
};
#pragma pack() //restore pack bit to 8

然后把类对象转换为结构体对象,然后依次写入二进制文件即可。这样生成的二进制文件就会按照结构体设计的格式来储存。成为这个文件的标准格式。把这个格式告诉其他任何开发平台和开发语言都能正确解析这个二进制文件。(这就是为啥不能用序列化储存工程文件的其中一个原因)。
那么把类对象转化为结构体对象后,在写入二进制文件之前,需要把结构体再次转化为char数组。这个时候就用到了下面的类型转换工具类:
typeconverter.h

#ifndef TYPECONVERTER_H
#define TYPECONVERTER_H

#include <QByteArray>

namespace MyUtil {

class TypeConverter
{
private:
	TypeConverter();

public:
	//note:these functions have to be write at header document
	template <class T>
	static void Struct2Byte(T &t, char *data) {
		memcpy(data,  &t, sizeof(t));
	}
	
	template <class T>
	static char* Struct2Byte(T &t) {
		char *data = new char[sizeof(t)];
		memcpy(data,  &t, sizeof(t));
		return data;
	}
	
	template <class T>
	static T* Byte2Struct(void *d) {
		T *t = static_cast<T*>(d);
		return t;
	}
	
	template<class T> //T is a pointer
	static T PointerForceConvert(void *d) {
		T t = reinterpret_cast<T>(d);
		return t;
	}
};

} //namespace MyUtil

#endif // TYPECONVERTER_H

typeconverter.cpp

#include "typeconverter.h"

namespace MyUtil {

TypeConverter::TypeConverter()
{
	//this function need to be at document of “cpp”
}

} //namespace MyUtil
发布了88 篇原创文章 · 获赞 45 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/robert_cysy/article/details/103854584