我需要对二进制数据执行一些正则表达式操作。我写了一个函数来转换六进制字符串表示中的QByteArray数据。每个字节前缀为'x'用于解析目的。
如何优化此代码?
QByteArray data;
QByteArray newData;
for (int i = 0; i < data.size(); i++) {
QString hex;
hex.setNum(data[i], 16);
if (data[i] < 10) {
hex.prepend("x0");
} else {
hex.prepend("x");
}
newData.append(hex.toLatin1());
}
答案 0 :(得分:1)
您发布的代码中有两个错误我已更正。
1)假设你总是想要两个十六进制数字,你想检查这个值是否小于16,而不是10。
2)QString::setNum
没有char的重载,因此该值被提升为更大的类型。对于128这样的值,在已签名的字符中为负数,由于符号扩展,您将获得x0ffffffffffffff80
。
函数foo1
是修复了错误的原始代码,foo2
是一个更优的版本,可以避免创建临时QString
,因为转换为unicode并且返回isn&#39 ; t free,并在字符串前加上值需要额外的复制。
我使用QElapsedTimer
,因为在我测试它的Windows上使用高分辨率PerformanceCounter时钟。如果您在另一个平台上,它可能不太准确。您可以在文档中看到它可能使用的不同类型的时钟。
如果您希望打印转换的字符串以验证它们是否相同,请将display_converted_string
设置为true。
#include <QString>
#include <QByteArray>
#include <QElapsedTimer>
#include <iostream>
QByteArray foo1(QByteArray data)
{
QByteArray newData;
for (int i = 0; i < data.size(); i++) {
unsigned char c = data[i];
QString hex;
hex.setNum(c, 16);
if (c < 16) {
hex.prepend("x0");
} else {
hex.prepend("x");
}
newData.append(hex.toLatin1());
}
return newData;
}
QByteArray foo2(QByteArray data)
{
static const char digits[] = {'0','1','2','3','4','5','6','7',
'8','9','a','b','c','d','e','f'};
QByteArray newData;
newData.reserve(data.size() * 3);
for (int i = 0; i < data.size(); i++)
{
unsigned char c = data[i];
newData.append('x');
newData.append(digits[(c >> 4) & 0x0f]);
newData.append(digits[c & 0x0f]);
}
return newData;
}
int main()
{
const int iterations = 10000;
const bool display_converted_string = false;
QElapsedTimer t;
std::cout << "Using clock type " << t.clockType() << ".\n";
QByteArray data(256, 0);
QByteArray newData;
qint64 elapsed1 = 0, elapsed2 = 0;
//Set the values in data to 0-255 to make sure all values are converted properly.
for(int i = 0; i < data.size(); ++i)
{
data[i] = i;
}
t.start();
for(int i = 0; i < iterations; ++i)
{
newData = foo1(data);
}
elapsed1 = t.nsecsElapsed();
std::cout << "foo1 elapsed time = " << elapsed1 << "\n";
if(display_converted_string)
{
std::cout << "newData = " << newData.data() << "\n";
}
t.restart();
for(int i = 0; i < iterations; ++i)
{
newData = foo2(data);
}
elapsed2 = t.nsecsElapsed();
std::cout << "foo2 elapsed time = " << elapsed2 << "\n";
if(display_converted_string)
{
std::cout << "newData = " << newData.data() << "\n";
}
return 0;
}