【问题标题】:Qt: from a fixed number of bytes to an integerQt:从固定字节数到整数
【发布时间】:2020-04-25 07:55:57
【问题描述】:

使用 Qt5.4,我构建了函数generateRandomIDOver2Bytes。它生成一个随机数并将其放入一个恰好占据两个字节的变量中。

QByteArray generateRandomIDOver2Bytes() {
    QString randomValue = QString::number(qrand() % 65535);
    QByteArray x;
    x.setRawData(randomValue.toLocal8Bit().constData(), 2);
    return x;
}

我的问题是恢复如此生成的值,以便再次获得一个整数。 以下最小示例实际上不起作用:

QByteArray tmp = generateRandomIDOver2Bytes(); //for example, the value 27458 
int value = tmp.toUInt(); 
qDebug() << value; //it prints always 9

有什么想法吗?

【问题讨论】:

  • 您知道randomValue 包含十进制数字的ASCII 字符中的随机数吗?这就是QString::number() 返回的内容。显然,对于 [0, 65535] 的范围,这将占用最多 5 个字节。如果要将 [0, 65535] 存储在两个字节中,则转换为字符串(文本)是一个不好的选择。 short(或std::uint16_t)(将其存储为二进制整数)就足够了,不是吗?然后您可以读取short 的两个字节并将它们存储到QByteArray 中。 (或者,我完全误解了你的意图吗?)
  • 你完全正确。事实上,我的问题可以归结为两点: 1-如何在 QByteArray 中转换一个 std::uint16_t ,它恰好占据两个字节?和 2- 如何恢复 QByteArray 并重新获得short?
  • 感谢您的努力 Scheff。我看到了 p-a-o-l-o 的答案,我正在尝试重现它。

标签: c++ qt qt5 byte qbytearray


【解决方案1】:

给定随机值 27458,当你这样做时:

x.setRawData(randomValue.toLocal8Bit().constData(), 2);

你正在用这个字符串的前两个字节填充数组:“27458”。

这里:

int value = tmp.toUInt();

字节数组被隐式转换为字符串(“27”),然后再转换为数值(无符号整数)。

让我们尝试一些不同的东西,也许适合你的需要。

首先,将值存储在数值变量中,可能是所需大小(16 位,2 字节):

ushort randomValue = qrand() % 65535;

然后只返回一个字节数组,使用指向ushort 的指针构建,转换为char *(不要使用setRawData,因为它不会复制您的字节把它传进去,还有解释here):

return QByteArray(reinterpret_cast<char *>(&randomValue), 2);

返回值:

QByteArray tmp = generateRandomIDOver2Bytes(); //for example, the value 27458

ushort value;
memcpy(&value, tmp.data(), 2);

请注意:类型在这里很重要。你在一个字节数组中写了一个uint,你必须从中读取一个uint

所有这些都可以概括为如下类:

template <typename T>
class Value
{
    QByteArray bytes;
public:
    Value(T t) : bytes(reinterpret_cast<char*>(&t), sizeof(T)) {}
    T read() const
    {
        T t;
        memcpy(&t, bytes.data(), sizeof(T));
        return t;
    }
};

所以你可以有一个通用函数,比如:

template<typename T>
Value<T> generateRandomIDOverNBytes()
{
    T value = qrand() % 65535;
    qDebug() << value;
    return Value<T>(value);
}

并安全地使用您喜欢的类型来存储随机值:

Value<ushort> value16 = generateRandomIDOverNBytes<ushort>();
qDebug() << value16.read();

Value<int> value32 = generateRandomIDOverNBytes<int>();
qDebug() << value32.read();

Value<long long> value64 = generateRandomIDOverNBytes<long long>();
qDebug() << value64.read();

【讨论】:

  • 谢谢你 p-a-o-l-o。你强调了我的一些弱点,但我确实学到了很多东西。我正在尝试复制它,我会尽快通知您。
  • 亲爱的 p-a-o-l-o,大多数似乎都还好。不幸的是,在 ushort 值之后打印“值”; memcpy(&value, tmp.data(), 2);总是返回 0。我不明白为什么。
  • 是的,我很好地返回了一个 return QByteArray(x); .我仍然有这个问题。但是,Scheff 的解决方案似乎对我有效。
  • @JoeMatt 我再次编辑了答案:只返回一个 QByteArray 并且根本不使用 setRawData。
  • 谢谢 p-a-o-l-o!我会尽快复制它。
【解决方案2】:

一个 16 位整数可以通过位操作拆分成单独的字节。

这样,它可以存储到QByteArray中。

来自 Qt 文档。 QByteArray:

QByteArray 可用于存储原始字节(包括“\0”)和传统的 8 位“\0”终止字符串。

对于恢复,也可以使用位操作。

QByteArray 的内容不一定会产生可打印的字符,但在这种情况下可能不需要(或不应该)。

testQByteArrayWithUShort.cc:

#include <QtCore>

int main()
{
  quint16 r = 65534;//qrand() % 65535;
  qDebug() << "r:" << r;
  // storing r in QByteArray (little endian)
  QByteArray qBytes(2, 0); // reserve space for two bytes explicitly
  qBytes[0] = (uchar)r;
  qBytes[1] = (uchar)(r >> 8);
  qDebug() << "qBytes:" << qBytes;
  // recovering r
  quint16 rr = qBytes[0] | qBytes[1] << 8;
  qDebug() << "rr:" << rr;
}

输出:

r: 65534
qBytes: "\xFE\xFF"
rr: 65534

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-10
    • 1970-01-01
    • 1970-01-01
    • 2019-02-12
    • 1970-01-01
    • 2016-05-14
    • 2018-03-08
    相关资源
    最近更新 更多