我有以下QByteArray
:
QByteArray ba;
ba.resize(3);
ba[0]=ba[2]=0x8a;
ba[1]=0x0d; //so ba=8a0d8a
我想在上面的QByteArray
上添加一个十六进制数。例如。添加0x01时,ba
应该包含8a0d8b
。涉及进位的任何此类操作都应像普通十六进制加法一样向前传播。我尝试使用+
运算符:
ba=ba+1;
,但它会串联(在上述情况下导致8a0d8a01
)而不是执行实际操作。该怎么办?
答案 0 :(得分:1)
首先,QByteArray中没有此类功能。但是,只要您知道字节数组将持续多长时间,就可以通过多种方法来解决。但是,有一件小事使事情变得更加复杂:Endianess。
以下示例假定所有字节数组都具有最大长度。该函数是通用的,因此您可以根据需要动态决定:
template <typename TInt>
void addNumber(QByteArray &data, TInt number) {
static_assert(std::is_integral<TInt>::value, "TInt must be an integral type");
constexpr auto maxSize = sizeof(TInt);
const auto dSize = data.size();
// make shure no data that is longer then the allowed integer size is passed
Q_ASSERT_X(dSize <= maxSize, Q_FUNC_INFO, "bytearrays longer than sizeof(TInt) byte are not allowed!");
// prepend '\0' bytes to the array to fill it up to an N byte length
if(dSize < maxSize)
data = QByteArray{maxSize - dSize, '\0'} + data;
// convert to a number, add and convert back
auto dataNum = qFromBigEndian<TInt>(data.constData());
dataNum += number;
qToBigEndian(dataNum, data.data());
// resize the data back to the original size, dropping the previously prepended bytes
if(dSize < maxSize)
data = data.mid(maxSize - dSize);
}
要使用该方法,只需找出您的字节数组可以使用多长时间,然后将其与相应类型一起使用即可。例如,如果数据限制为最多4个字节(如命令中指定),则可以将其用作:
QByteArray ba = "\x8a\x0d\x8a";
addNumber<quint32>(ba, 1u);
// ba is now "\x8a\x0d\x8b"
重要:请谨慎使用template参数。明确指定它,以确保您不会意外地传递其他类型的文字。例如,简单地将其命名为addNumber(ba, 1)
会得出TInt
为int
的含义-而不是未整数的整数。
编辑: 如果您将字节数组的字节序定义为与当前平台相同,则无需进行此类转换。该代码将更改为:
// convert to a number, add and convert back
*(reinterpret_cast<TInt*>(data.data())) += number;
这实际上取决于这些数据的来源和使用方式。
答案 1 :(得分:1)
我认为这是最简单的解决方案:
uint32_t num = (b[3] << 24) + (b[2] << 16) + (b[1] << 8) + (b[0]);
num++; // add one
b[0] = num & 0xff;
b[1] = (num >> 8) & 0xff;
b[2] = (num >> 16) & 0xff;
b[3] = (num >> 24) & 0xff;
基本上,您可以来回转换为算术整数。只要确保您不会溢出即可。这是一个简单的例子。您可以将其设为状态,使其在某种方法上返回QByteArray
的类,也可以使函数一次执行一次此操作。
答案 2 :(得分:0)
为什么不使用像
这样的简单数据?template <typename T> union BData
{
uint8_t data[sizeof(T)];
T value;
};
然后,您可以执行算术运算并从并集提取字节。但是,您应该注意耐力。