Qt: от фиксированного числа байтов до целого числа - PullRequest
1 голос
/ 07 января 2020

Используя 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

Есть идеи?

Ответы [ 2 ]

1 голос
/ 08 января 2020

16-битное целое число может быть разбито на отдельные байты с помощью битовых операций.

Таким образом, оно может быть сохранено в QByteArray.

Из Qt do c. из 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
1 голос
/ 08 января 2020

Учитывая случайное значение 27458, когда вы делаете это:

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

вы заполняете массив первыми двумя байтами этой строки : "27458".

И здесь:

int value = tmp.toUInt();

байтовый массив неявно преобразуется в строку ("27"), которая, в свою очередь, преобразуется в числовое значение c (целое число без знака).

Давайте попробуем что-то другое, что, возможно, подойдет вам.

Сначала сохраните значение в переменной Numberri c, возможно, нужного размера (16 бит, 2 байта):

ushort randomValue = qrand() % 65535;

, затем просто возвращайте байтовый массив, построенный с использованием указателя на ushort, приведенный к char * (не используйте setRawData, потому что он не copy байты, которые вы передаете, также объяснили здесь ):

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;
    }
};

, чтобы вы могли иметь обобщенную c функцию, такую ​​как:

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();
...