Qt/QString: No compiler error on misplaced parenthesis - qt

I just created a qstring from a double, but I misplaced the parenthesis. It did compile and the QString was fine in my computer, but the string had a lot of added garbage data data in front of the "1500 m" string I was producing in my friends computer.
My question is: What is actually going on in this codeline. Why doesn't it produce a compiler error?
double distance = 1500;
QString distanceString = QString("%1 m").arg(QString::number(distance), 'f', 1);
No compiler errors, and different behaviour on different computers.

QString("%1 m").arg(QString::number(distance), 'f', 1)
is calling the 3-argument overload
QString::arg(const QString &a, int fieldWidth, QChar fillChar)
So in this case, your parameters will go through implicit conversions:
'f' converts to int, which is 102
1 converts to char and which ends up being the SOH ASCII character
Becuase these conversions are allowed to happen implicitly, the call to arg is well-formed and so this is not a compile error.
The function then will do what is designed to do and replace "%1" with your number, but padded to a length of 102, padded with the unprintable SOH character. So you end up with a strange looking output.

Related

Need to understand how char * strcpy (char *cad1, const char *cad2) works in C

Can't get how a method with this head: char * strcpy (char *cad1, const char *cad2), works in C in this sample:
'char * strcpy (char *cad1, const char *cad2){
char *aux = cad1;
for( ; *cad1++ = *cad2++; );
return cad1;
}'
Starting from the method signature or prototype, that tells a lot about the how it works: we have two parameters together with their respective types and a return type. All parameters in this case are pointers to char, more known as char pointers. Those char pointers are what is used in "C" as strings of characters. One parameter is a const, because that value must not be changed in the function, it MUST keep, the original value.
Strings in "C" have some peculiarities, once the pointer is created to a string it always points to the first characters in the string or index 0, the same as char *v = var[0], and can be incremented passing to the next char in the string such as v++. Other peculiarity in "C" is that all strings represented by char arrays end with a 0 character (ASCII null = 0).
The strcpy version account on that concepts and makes a for loop to copy each element in the char *cad2 to *cad1, that variables MUST be allocated statically or dynamically (malloc) before calling the function, and the return of the function in the code above is a pointer to the original variable (in that case *cad1, normally they return the copied one). In your function it was changed, I mean it is returning the original instead of the copied what looks wrong since you catch in the aux the pointer to the first element of the copied variable and you did not use it.
One good point to observe is the for loop:
for( ; *cad1++ = *cad2++; );
How it works is tricky, the first interesting point is that the for loop has tree parameters, and in "C" all are optional. The first is to initialize, the second is a boolean condition to continuing iterating, and the last one is to increment or decrement.
Next, tricky is is *cad1++ = *cad2++ a boolean expression? The answer is yes, it is. Since in "C" the value 0 (zero) is false, and anything else is true. Remember that I have said strings in "C" finishes always with a 0 (zero), so when evaluating and assigning to the copy the value of a pointer (using *cad1 will return the value pointed by a pointer variable, the star in the begin makes that magic) and reaches the end of the string that will return false and finish the iteration loop.
One point is interesting here, first the evaluation has less priority than the assignment in this case, what makes first the value being copied to the copy variable, then evaluating the boolean expression.
"C" is like this you writes a small code that have large meaning behind it. I hope you have understood the explanation. For further information have a look in "C" pointers at : https://www.tutorialspoint.com/cprogramming/c_pointers.htm.
char * strcpy (char *cad1, const char *cad2){
for( ; *cad1++ = *cad2++;);
return cad1;
}
the way this works, at the calling side, it can be used in two ways, but always requires a buffer to write to so the use is simmilar.
char arr[255];
memset(arr,0,sizeof(char) * 255); // clear the garbage initialized array;
strcpy(arr, "this is the text to copy that is 254 characters long or shorter.");
puts(arr);
or
char arr[255];
memset(arr,0,sizeof(char) * 255);
puts(strcpy(arr,"hello C!"));
sense the function returns the pointer to the buffer this works as well.

How can a 1 byte int conversion of a QByteArray fail?

So here is the thing, I'm receiving 1 byte from Bluetooth transmission. When using QDebug I get this message:
The array with error has "\x06"
The line that fails is this:
bool ok = true;
int v = value.toInt(&ok,0);
Because ok has false. But I'm trying to wrap my head around the fact that, How can the conversion fail in the first place if the data represented in that byte (as a sequence of zeros and ones) will always have a valid integer representation. (one byte can always be represented as a int between -127 and 128). So I'm left with the question, how can the conversion fail?
Reading the documentation does not provide many clues as it does not say how the byte array will be interpreted.
QByteArray::toInt converts a string representation in the default C locale to an integer. That means to successfully convert the value in your example, your byte array must contain the string "0x06", which consists of 4 bytes.
To convert a single byte to an int, just extract it:
int i = value[0];
Type promotion will widen the char to an int

QRegExp and Null Character in Qt

i want search in a binary file with regular expression.
my search is successful in Text files, but not match in binary file, because QRegExp in function indexIn stop search when meet the NULL Character (chr(0)).
what can i do to solve this problem?
QString can contain null characters, it's just its constructors that are inconsistent...
QString::fromUtf8(const char *str, int size = -1) uses the given size, while QString::fromUtf8(const QByteArray &str) forces a strlen instead of using the bytearray size. See for yourself Qt code.
QRegExp also supports null characters:
QString s(QChar(0));
QRegExp re(s);
qDebug() << re.indexIn(s); // will print 0, not -1

How can i split a wchar_t / TCHAR / WCHAR / LPTSTR into a QStringList?

While working with the Win32API, the function i must use returns its results by writing them to buffer of type LPTSTR as well as the individual number of characters that were written.enter code here
As this buffer is a string, and the function can return multiple values, the actual result data look something like this:
Value1\0Value2\0Value3\0\0
What is the best way to get this into a QStringList?
LPTSTR = Long Pointer to TCHAR. On modern systems (those with unicode support) this is synonymous with a WCHAR array.
Since your output buffer will contain characters where each is two bytes it is thus compatible with UTF16.
QString has a fromUtf16 static method which requires a simple cast to satisfy the compiler.
In this case, we MUST also specify the total length of the entire string. Failure to do this results in QString only reading the input data up until the first null character, ignoring any other result data.
Once we actually have a QString to work with, splitting it is simple. Call QString's split() method specifying a null character wrapped in a QChar.
Optionally, and required in my case, specifying SplitBehavior as SkipEmptyParts ensures that no empty strings (the result of parsing the null character) end up in my desired result (the QStringList of values).
Example:
// The data returned by the API call.
WCHAR *rawResultData = L"Value1\0Value2\0Value3\0";
// The number of individual characters returned.
quint64 numberOfWrittenCharacters = 22;
// Create a QString from the returned data specifying
// the size.
QString rString =
QString::fromUtf16((const ushort *)rawResultData, numberOfWrittenCharacters);
// Finally, split the string into a QStringList
// ignoring empty results.
QStringList results =
rString.split(QChar(L'\0'), QString::SkipEmptyParts);

Storing a char in a char pointer

I have a global variable that is a *char. My main function header reads as int main(int argc, char* argv[argc]){...}. These two lines of code have to remain the way they are. The first argument of my main function is a number of type *char, that I convert to a char using atoi(...);. I am basically changing the ASCII value to its corresponding character. Now I want to store this local variable character I have into the global variable that is a char pointer. I know the problem is related to allocation of memory, but I am not sure how to go about this.
My code:
char* delim;
int main(int argc, char* argv[argc])
{
char delimCharacter;
if (isdigit(*(argv[3])) == 0) delim = argv[3]; //you can pass in a character or its ascii value
else { //if the argument is a number, then the ascii value is taken
delimCharacter = atoi((argv[3]));
printf("%s\t,%c,\n", argv[3], delimCharacter);
//sprintf( delim, "%c", delimCharacter ); // a failed attempt to do this
*delim = delimCharacter;
//strncpy(delim, delimCharacter, 1); // another failed attempt to do this
}
//printf("%s\n",delim);
This yields a seg fault.
You need to verify you have got (at least) 3 arguments before you start using them.
if (argc < 4)
{
printf("Need 3 args");
exit(1);
}
Then you need to allocate some memory to put the character in.
delim = malloc(2);
// TODO: Should check the result of malloc before using it.
*delim = delimCharacter;
delim[1] = 0; // Need to NULL terminate char*
You're dereferencing an uninitialized pointer. delim never gets initialized when it goes into the else block.
char delim[] = ","; // anything really, as long as as it's one character string
...
delim[0] = delimCharacter;
In addition to your memory issue, I think you are confused about what atoi does. It parses a string representation of a number and returns the equivalent int value, e.g. "10000" => 10,000. I think that you think it will give you the ASCII value of a character, e.g. "A" =>65.
Since you have a char *, and you are (I think) assuming that it contains a single character, you could simply do this:
delimCharacter = *(argv[3]);
However, there really seems to be no need to use the intermediate step of assigning this value to a char variable at all. If the end goal is to have delim point to the char that is the delimiter, then it seems this is all you need to do:
delim = argv[3];
Not only does this remove unnecessary code, but it means you would no longer need to allocate additional memory for delim to point to.
I would also declare delim as a const char * since I assume there is no reason to change it.

Resources