【问题标题】:Is there an easy way of using the QVariant class with hexadecimal strings?有没有一种简单的方法可以将 QVariant 类与十六进制字符串一起使用?
【发布时间】:2012-02-09 10:35:47
【问题描述】:

此代码示例按我的预期工作:

v = QVariant("123456");
qDebug() << v; // QVariant(QString, "123456")
v.convert(QVariant::Int);
qDebug() << v; // QVariant(int, 123456)
v.convert(QVariant::String);
qDebug() << v; // QVariant(QString, "123456")

如果不是这样:

v = QVariant("0xBEEF");
qDebug() << v; // QVariant(QString, "0xBEEF")
v.convert(QVariant::Int);
qDebug() << v; // QVariant(int, 0)
v.convert(QVariant::String);
qDebug() << v; // QVariant(QString, "")

是否有任何简单的方法可以使 QVariant 类使用十六进制字符串,所以第二个示例可以像这样工作:

v = QVariant("0xBEEF");
qDebug() << v; // QVariant(QString, "0xBEEF")
v.convert(QVariant::Int);
qDebug() << v; // QVariant(int, 48879)
v.convert(QVariant::String);
qDebug() << v; // QVariant(QString, "48879")

【问题讨论】:

    标签: qt hex qvariant


    【解决方案1】:

    将 qvariant 转换为数值时,您需要指定基数。还要确保该值适合 int/long/longlong,否则转换将因此而失败。

    QVariant v = QVariant("0xDEADBEAF");
    bool test;
    qDebug() << v.toString().toLongLong(&test,16);
    qDebug() << test;
    

    会产生正确的输出

    3735928495 
    true 
    

    同时

    QVariant v = QVariant("0xDEADBEAF");
    bool test;
    qDebug() << v.toString().toInt(&test,16);
    qDebug() << test;
    

    会输出

    0
    false
    

    【讨论】:

    • 好点,我已经更新了我的问题以反映一个更明智的例子。但是我认为你失败的理由是不正确的。 "0xBEEF" 转换为 0 而不是不会溢出的 48879。话虽如此,如果您删除不正确的位并将其更新以匹配修改后的问题,我将很乐意接受您的回答,因为这是一个很好的解决方案,谢谢。 :)
    • 是和不是。在 QVariant::convert() 的情况下,它首先失败,因为它不知道从哪个基础转换。这也发生在“0xBEEF”的情况下。但是,如果您指定基数,它就会失败,因为它无法将“0xDEADBEEF”转换为合法的整数,因为溢出。因此 QVariant("OxBEEF").toString.toInt(&test,16) 会成功,而 QVariant("OxDEADBEEF").toString.toInt(&test,16) 不会。我会更新我的答案。
    • 正确,但是存储为字符串的数字的 QVariant 转换例程会根据字符串中包含的字符(即"1" == 1,但不在"m1stake" 中)进行尝试。我希望让它对存储在 C++ 表示法中的十六进制字符串做同样的尝试(即 "a" == 10"0xa" 但不是在"di0xan" 中)。 QVariant 似乎并没有费心做出任何这样的尝试(基于我的"0xBEEF" 示例的结果)。
    • 我认为它只是假设它的基数为 10 并且如果不是则失败。 QString::toInt() 的默认值是 10,我猜这就是 QVariant::convert() 调用来进行转换的函数。
    • 不是这样。 And I'll tell you for why! 再次感谢您回答我的问题让我在 QVariant 中找到了那个错误 :)
    【解决方案2】:

    this answer 提出关于数值溢出的观点后,我做了一些调查,似乎 QVariant 的转换例程存在缺陷。安全地转换 QVariant 的最简单方法是使用 QString 的转换。这似乎也是将 QVariant 与十六进制字符串一起使用的最简单方法。我在下面总结了我的发现。 cmets 将是在代码中此时调用qDebug() &lt;&lt; v; 的结果输出。

    场景一:数字存储为十六进制字符串

    v = QVariant("0xBEEF"); // 'QVariant(QString, "0xBEEF") '
    v = v.toString().toInt(0, 16); // 'QVariant(int, 48879) '
    
    v = QVariant("0xDEADBEEF"); // 'QVariant(QString, "0xDEADBEEF") '
    v = v.toString().toInt(0, 16); // 'QVariant(int, 0) '
    

    将表示十进制数的字符串转换为数字类型的最简单和最安全的方法是使用 QString 的toInt(bool * ok = 0, int base = 10) 方法。

    场景 2:数字存储为十进制字符串

    v = QVariant("123456"); // 'QVariant(QString, "123456") '
    v.convert(QVariant::Int); // 'QVariant(int, 123456) '
    

    QVariant 的convert(Type t) 方法在这种情况下按预期工作。

    v = QVariant("2147483649"); // 'QVariant(QString, "2147483649") '
    v.convert(QVariant::Int); // 'QVariant(int, -2147483647) '
    
    v = QVariant("9223372036854775807"); // 'QVariant(QString, "9223372036854775807") '
    v.convert(QVariant::Int); // 'QVariant(int, -1) '
    

    但是,当字符串包含对于数据类型来说太大的数字时,使用相同的方法会导致静默溢出,而不是做一些更有用的事情,比如返回 false 并将 QVariant 设置为 0。

    v = QVariant("2147483649"); // 'QVariant(QString, "2147483649") '
    v = v.toString().toInt(); // 'QVariant(int, 0) '
    
    v = QVariant("9223372036854775807"); // 'QVariant(QString, "9223372036854775807") '
    v = v.toString().toInt(); // 'QVariant(int, 0) '
    

    通过使用与场景 1 中相同的方法,可以防止这种情况发生,还可以使用 toInt() 的可选参数 *bool 来提醒失败。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-19
      • 1970-01-01
      • 2015-12-23
      • 1970-01-01
      • 1970-01-01
      • 2010-09-17
      • 2020-10-21
      • 2020-11-25
      相关资源
      最近更新 更多