2014-05-24 29 views
0

我需要對二進制數據執行一些正則表達式操作。我寫了一個函數來轉換六字符串表示形式的QByteArray數據。爲了解析目的,每個字節都以'x'爲前綴。如何優化這個Qt代碼(QByteArray轉換)?

該代碼如何優化?

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()); 
} 
+1

這個問題似乎是題外話題,因爲它是關於代碼審查。 – lpapp

回答

1

您發佈的代碼中有兩個錯誤,我糾正了。

1)假設你總是希望要查詢兩個十六進制數字如果該值小於16,而不是10

2)QString::setNum沒有過載炭,因此該值被提升到一個更大的類型。對於像128這樣的值,在簽名字符中爲負數,由於符號擴展,您將得到x0ffffffffffffff80

功能foo1是你原來的代碼修復的錯誤,並foo2是避免創建自轉換爲Unicode臨時QString更優化的版本,後面是不是免費的,前面加上值的字符串需要額外的複製。

我使用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; 
}