Question

This code sample works as I would expect:

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")

Where as this doesn't:

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, "")

Is there any simple way to make the QVariant class work with hexadecimal strings so the second example would work something like this:

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")
Was it helpful?

Solution

When converting a qvariant to a numeric value you need to specify the base. Also make sure the value will fit in the int/long/longlong or then the conversion will fail for that reason instead.

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

will produce the correct output

3735928495 
true 

while

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

will output

0
false

OTHER TIPS

After the points made by this answer about numerical overflow, I did some investigation and it seems the QVariant's conversion routines are flawed. The easiest way way to convert a QVariant safely is by using QString's conversions instead. This also seems like the easiest way to use QVariant with hexadecimal strings. I've summarised my findings below. The comments would be the resulting output of making a call to qDebug() << v; at that point in the code.

Scenario 1: Number stored as a hexadecimal string

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) '

The easiest and safest way of converting a string-which-represents-a-decimal-number into a number type is by using QString's toInt(bool * ok = 0, int base = 10) method.

Scenario 2: Number stored as a decimal string

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

QVariant's convert(Type t) method works as one would expect in this scenario.

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) '

However using the same method when the string contains a number that is too large for the data type causes a silent overflow, instead of doing something more useful like returning false and setting the QVariant to 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) '

By using the same method as in Scenario 1, one can prevent this from happening and also use the optional *bool parameter of toInt() to be alerted of failures.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top