【问题标题】:Qt converting string to int in base 16 but remain the value of base 16Qt 将字符串转换为以 16 为基数的 int 但保持以 16 为基数的值
【发布时间】:2018-08-15 02:57:23
【问题描述】:

这已经困扰我好几天了,我真的不知道要麻烦你们。

我在Qt 中有一个输入,可以从用户输入中获取任何数字。

用户输入数字后,我得到数字并转换为十六进制(base 16),如果十六进制大于1字节,我将其拆分为1字节大小。我已经完成了所有的转换和拆分。

现在我的问题是,在我转换和拆分之后,十六进制停留在QString的数据类型中,但是为了在QBtyeArray中发送,我需要转换回int。

你们能告诉我有什么方便的方法可以将 QString 转换回 int 吗?我尝试了很多方法,但是所有的转换都给了我以 10 为底的值,我希望该值以 16 为底,但在 int 中。

示例:用户在 lineEdit 中输入 10800(以 10 为底),我从 lineEdit 中检索 10800,然后将其转换为以 16 为底,因此 10800 的十六进制为 2A30 ,在我进行转换后,值2A30 在 string 中,我可以知道如何将类型转换为 int 但值仍保持为 2A30 但不会转换回 10800(基数 10)。

我得到的最接近的答案是通过这种方法

unsigned int value = QString("0x2A").toUInt(&ok, 16);

int abcde = sprintf(abc, "%x", value);

qDebug()<<QString::number(value);

QByteArray test_a = abc; 

但它要么返回我 QByteArray 或 char,我希望它在 int 中,因为我需要指定我在这样的 writeDatagram() 函数中发送的每个字节。

 QByteArray datagram(4, '\x000');
    datagram[0] = 0x02;
    datagram[1] = 0x10;
    datagram[2] = 0x00;
    datagram[3] = 0x00;

如果我的问题不够清楚,请告诉我。我正在使用Qt 5.2.1

谢谢!!!

【问题讨论】:

  • 您的问题假定有解决方案,但没有说明您要解决的问题。请在开头添加一个段落,提供至少 2 或 3 个寻求 输入 的示例到转换(即用户输入了什么字符串),以及您期望的 输出 (即QByteArray 的内容)。
  • @KubaOber 我已经添加了一个新示例,用户期望的输入是 int in base 10 ,之后我需要转换为 base 16 ,但是在我将类型转换为 QString 之后,所以我想将其转换回 int 但值保持我转换的值。明白了吗 ?如果没有,请再告诉我一次。我会尽量解释得更清楚。
  • 不清楚您要的是什么。当存储在 int 中时,10800 和 0x2a30 是相同的数字。十进制和十六进制是显示相同值的不同方式。
  • 对不起,我知道是相同的值,但是当我通过 QByteArray 发送时,byteArray 只接受 int ,所以我需要将数据类型从 String 转换为 Integer .. 我得到了指定什么我需要在下面发送数据报。我需要指定每个字节要发送什么。所以我必须拆分并将其转换为 int 并放入 datagram[] 字节数组中。
  • 准确显示字节数组中的字节数!!!!。我们猜测您想要的字节是0x2a0x30,但是按照什么顺序,我们猜对了吗?您正在为转换编写规范:所以编写规范。规范必须提供一些示例。输入是QString,输出是QByteArray。显示一些对 {string, array} 以展示您认为正确的输入-输出对。问题中的大部分文字都是不相关的。例如,您在数据报中显示\x02\x10\x00\x00:为什么?!使用有助于您的规范的示例!

标签: c++ qt


【解决方案1】:

为什么要进行转换等?我假设您想发送一个任意长的整数,有效地以 256 为基数,即一次一个字节,而不是一次说一个十进制数字。我还假设您想代表它们大端,即最重要的 base-256 数字首先出现。假设您必须发送 12384928,它将作为字节 188、250、160(0xbc、0xfa、0xa0)发送。

这很容易做到:

QByteArray numberToBytes(const QString &number) {
  QByteArray result;
  bool ok = false;
  auto value = number.toLongLong(&ok);
  if (ok) {
    int n = sizeof(value);
    while (value && n--) {
      result.append(quint8(value & 0xFF));
      value = value >> 8;
    }
    std::reverse(result.begin(), result.end());
  }
  return result;
}

QString bytesToNumber(const QByteArray &bytes) {
  qlonglong value = 0;
  for (auto b : bytes)
    value = (value << 8) | quint8(b);
  return QString::number(value);
}

void test() {
  Q_ASSERT(sizeof(qlonglong) == 8);
  Q_ASSERT(numberToBytes("256") == QByteArray::fromRawData("\x01\x00", 2));
  Q_ASSERT(numberToBytes("2134789") == QByteArray::fromRawData("\x20\x93 \x05", 3));
  Q_ASSERT(numberToBytes("-58931") == QByteArray::fromRawData("\xFF\xFF\xFF\xFF\xFF\xFF\x19\xCD");
}

您可能还认为数字太长而无法容纳 8 个字节。这些需要稍微复杂的基数更改操作 - 毕竟,您真的不想进行重复的长除法。详情请见this page

但看起来你只是想在数据报中发送字符串。如果您希望将校验和(此处为:CCITT CRC-16)附加到数据中,这也不难,因为 Qt 为我们做到了:

QByteArray serialize(const QString &str, bool withCRC = false) {
  QByteArray result;
  QDataStream ds(&result, QIODevice::WriteOnly);
  ds << str;
  if (withCRC) ds << qChecksum(result.constData(), result.size());
  return result;
}

QString deserialize(const QByteArray &packet, bool withCRC = false) {
  QString result;
  QDataStream ds(packet);
  ds >> result;
  if (withCRC) {
    quint16 crc;
    ds >> crc;
    crc ^= qChecksum(packet.data(), packet.size() - 2);
    if (crc) return {};
  }
  return result;
}

数据报的格式如下:字符串长度(4 个字节),后跟字符串中的每个字符(每个 2 个字节 - 它是一个QChar)。可选的 CRC 是另外 2 个字节。仅此而已。

如果字符串只有 ASCII 字符,那么如果字符串很长,发送 UTF-8 表示将占用一半的空间:

QByteArray serialize(const QString &str, bool withCRC = false) {
  QByteArray result;
  QDataStream ds(&result, QIODevice::WriteOnly);
  ds << str.toUtf8();
  if (withCRC) ds << qChecksum(result.constData(), result.size());
  return result;
}

QString deserialize(const QByteArray &packet, bool withCRC = false) {
  QByteArray result;
  QDataStream ds(packet);
  ds >> result;
  if (withCRC) {
    quint16 crc;
    ds >> crc;
    crc ^= qChecksum(result.constData(), result.size());
    if (crc) return {};
  }
  return QString::fromUtf8(result);
}

也许你试图通过提前知道它是一个数字来使字符串更小,从而以最佳方式表示它。您希望这些字符串有多长,您对数据报大小的限制是多少?

【讨论】:

  • 我想通过 QUDPSocket 发送,抱歉我没有提到。所以我必须发送 QByteArray 并且我需要确定我发送的数据的大小,例如 10800 在字符串中是 5 个字节,但在十六进制中只有 2 个字节(0x2A 和 0x30)所以我总共只需要发送2 个字节通过 UDP 套接字。我已经完成了 UDP 套接字,并且我有一个函数调用 writeDatagram() 来处理它。所以现在我关心的是如何将 0x2A 和 0x30 转换为 int ,现在我的 2A 和 30 在字符串中。
  • @Reggie 你什么都不用做。使用QDataStream,它将为您序列化和反序列化字符串。你为什么要把这件事弄得这么复杂?
  • 我刚接触 Qt ,以前从未使用过 Qt。这已经困扰了我好几天了。我试过 QDataStream 可以通过 QByteArray 发送吗?并且大小也将保持 2 个字节?
  • 我之前尝试过 QDataStream,但在我的情况下似乎不起作用..或者我做错了。我再试一次看看。
  • 大小根本不需要保持2字节。这是一个无关紧要的细节。您在一端推送QString,在另一端收到QString。这就是你所关心的。 QString 甚至不需要携带数字。它可以是任何东西。您可以将莎士比亚的一本书复制粘贴到输入行中,然后在另一端输出相同的内容。
猜你喜欢
  • 2012-06-20
  • 1970-01-01
  • 1970-01-01
  • 2019-07-19
  • 2019-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多