PDA

View Full Version : issue char * hex buffer to QString conversion to print to textEdit Widget



bobth12
7th April 2014, 17:55
Hi,

I am new to QT, but have been programming in C/C++. I have a question regarding displaying hex values to TextEdit Widget. I have tried various method, but sometimes some of the hex values change or sometime the output is totally different.

So I have a char buffer like this:

1st implementation:


char * cHexData = new char [HexBuff_size+1];
memset(cHexData, '\0', HexBuff_size+1);
char * temp_iter = cHexData;

for (int i = 0; i<(HexBuff_size+1); i++){
sprintf(temp_iter ,"%X",(unsigned char)HexBuff[i]); //HexBuff is char buffer of size 256 and it holds the some data
temp_iter++; // I am printing putting the values to cHexData buffer which will hold hex values
} //ex: cHexData = FF6C69.....


//now i need to convert it to QString so that I can out the same Hex value in cHexData with formatting
for (int i = 0; i<(HexBuff_size+1); i++){

if (i!=0 && i%2==0) //append whitespace every 2 char
QTtext_qsPrintData+=" ";

if(i!=0 && i%16 ==0) //every 16th hex value newline
QTtext_qsPrintData+= "\n";

QTtext_qsPrintData+=QString(QChar(cHexData[i]));
}

ui->textWid->setText(QTtext_qsPrintData);

//output i want is;
//FF 6C 69... <- so same hex value as in cHexData.
//25 C8 95...
//...



So this implementation; when in Debug mode(breakpoints) has the correct Hex value for QTtext_qsPrintData as cHexData, which is good. But in the release version, on every run, some of the Hex values in QTtext_qsPrintData changes. That in turn will display the values wrong on the output
So after reading about hex value and QString conversion; I tried the following:




...
iNumWhiteSpace = (HexBuff_size/2); //number of whitespace between 2 hex values
iNumReturns = (HexBuff_size/16)-1; //\n every 16th hex value;

for(int i = 0 ; i<HexBuff_size; i ++){
if (i!=0 && i%2==0){
*temp_iter=' ';
temp_iter++;
}
if(i!=0 && i%16 ==0){
*temp_iter='\n';
temp_iter++;
}

sprintf(temp_iter ,"%X",(unsigned char)HexBuff[i]);
temp_iter++;

}

q_bHex = QByteArray(reinterpret_cast<char*>(cHexData ), HexBuff_size+iNumWhiteSpace+iNumReturns+1);
//and QByteArray q_bHex(cHexData , HexBuff_size+iNumWhiteSpace+iNumReturns+1);
ui->textWid->setText(QString(q_bHex));



// This implementation is also same as above

I have also looked into something like; but the values are decimal, and that make sense since my char * buffer already have hex values.


//for (int i=0 ; i < HexBuff_size; i++)
// QTtext_qsPrintData+= QString("%1").arg(cHexData[i],0,16);



please help with this. I was not too sure if I should post it here or QT newbie; If I have posted it in the wrong forum please move it.

Thanks!

Infinity
7th April 2014, 21:18
Just convert each character of your C-style character array to an integer and add it to a QString:


QString result;
result.reserve(3 * arraySize - 1);
for(char* i = array, end = array + arraySize; i < end; ++i) {
if(!result.isEmpty()) {
result += QLatin1Char(' ');
}
result += QString("%1").arg(static_cast<uint>(*i), 2, 16, QLatin1Char('0'));
}
hexLineEdit->setText(result);

That's just an quick draft. I haven't tested it.
I recommend to avoid the usage of C-style arrays and C-style casts in C++.

ChrisW67
8th April 2014, 00:31
This code is faulty and dangerous.


char * cHexData = new char [HexBuff_size+1];
memset(cHexData, '\0', HexBuff_size+1);
char * temp_iter = cHexData;

for (int i = 0; i<(HexBuff_size+1); i++){
sprintf(temp_iter ,"%X",(unsigned char)HexBuff[i]); //HexBuff is char buffer of size 256 and it holds the some data
temp_iter++; // I am printing putting the values to cHexData buffer which will hold hex values
} //ex: cHexData = FF6C69.....



If you are going to convert N bytes into a hexadecimal string you need a target buffer at least 2N+1 bytes long to avoid the possibility of overrunning the buffer. In this case, your 256 source bytes require a 513 byte output buffer.

You convert each successive byte into one (i.e. no 0 padding for values < 16) or two hexadecimal digits in the target buffer and then advance the pointer by one character. You need to consistently convert each byte to two characters ("%02X") and advance by two chars.

If you already have the input buffer and know its size:


QByteArray temp = QByteArray::fromRawData(input, inputBufferSize);
QString output = QString(temp.toHex());

bobth12
8th April 2014, 20:14
Hi ChrisW67,

You are absolutely correct. That was not the original size. My code did do [2*size+1+other sizes] which needed me to show my other codes. So just for simplicity i did that; for sprintf I used "%.2X".


--Back to the topic.

This is weird. Not sure what happened...now before ChrisW67's modification i tired I Infinity's



QString result;
result.reserve(3 * arraySize - 1); // <------------at this line I was getting Malloc(): memory corruption:confused:
for(char* i = array, end = array + arraySize; i < end; ++i) {
if(!result.isEmpty()) {


So i removed your code Infinity's suggestion and tried ChrisW67

Still I get this Malloc(): memory corruption.

When i commented ChrisW67's suggestion out and make it look like before where the code worked. The memory corruption issue is still show. So i tried re-starting the machine, tired re-creating the project; no luck.

Here is my code after the QString conversion function.


tempData = QByteArray::fromRawData(cHexData , ((HexBuff_size*2)+iSizeofWhite+iSizeofRet+1) );
QTtext_qsPrintData= QString(tempData.toHex());

ui->textWid->setText(QTtext_qsPrintData);
delete [] cHexData ;
cHexData = NULL;
temp_iter= NULL;



If I comment out lines 1-4 I get the following:
double free or corruption (!prev):...
malloc(): memory corruption:...

But it worked before. :confused:

Thanks!

Added after 1 44 minutes:

Okay so i was able to fix the memory corruption issue. However, I am still having trouble with outputting hex values



tempData = QByteArray::fromRawData(cHexData , ((HexBuff_size*2)+iSizeofWhite+iSizeofRet+1) );
QTtext_qsPrintData= QString(tempData.toHex());

ui->textWid->setText(QTtext_qsPrintData);


After line 4 the values displayed in the GUI are all decimal values. If i put a breakpoint, tempData has the correct hex values. But doing tempData.toHex() converts everything to decimal. Please note: cHexData already has hex values. I want to display those values.

Infinity
8th April 2014, 22:28
I've tested my code. There have been mistakes, but none of them leads to memory corruption.
Just for completeness, that's a slightly improved version of my former draft which seems to work:


static const int width = 5;
QString result;
result.reserve(3 * arraySize - 1);
int numInLine = 0;
for(unsigned char *i = array, *end = array + arraySize; i < end; ++i, ++numInLine) {
if(numInLine >= width) {
result += QLatin1Char('\n');
numInLine = 0;
}
if(numInLine > 0) {
result += QLatin1Char(' ');
}
result += QString("%1").arg(static_cast<int>(*i), 2, 16, QLatin1Char('0'));
}

Using the toHex method of QByteArray class has the disadvantage that you don't get whitespaces and new lines, but it should work of course. I think the way you're filling your array is the problem. Show us the relevant code.

cHexData already has hex values
Your variable contains a number. The binary system is used to store the value internally (and to do calculations). The decimal or hexadecimal number system comes only into play when displaying the number.

ChrisW67
9th April 2014, 00:02
Please note: cHexData already has hex values. I want to display those values.
If cHexData is a pointer to a C-style string of [0-9A-F] and whitespace chars that you simply want to display then:


const char *cHexData = "51 74 20 43 65 6E 74 72 65";
QString result(cHexData);
// or
QString result = QString::fromLatin1(cHexData);

or if the buffer is not NUL terminated:


const char cHexData[] = {'5', '1', ' ', '7', '4', ' ', '2', '0', ' ', '4', '3', ' ', '6', '5', ' ', '6', 'E', ' ', '7', '4', ' ', '7', '2', ' ', '6', '5'};
const int charCount = sizeof(cHexData);

QString result = QString::fromLatin1(cHexData, charCount);

bobth12
9th April 2014, 20:19
Hi,

Thanks to both of you for the support.

I went with:


QString result = QString::fromLatin1(cHexData, charCount);