How to get correct QString from "\u0000"? - qt

Sometimes I receive QString with value "\u0000" and I want to check if the received string equals to "\u0000".
But when I try:
qDebug() << QString("\u0000") << QString::fromUtf8("\u0000");
I get output: "\u0001" "\u0001"
So as a result I can not compare the strings. I see that initially this string was created using snprintf from byte to get char* and then created std::string and QString from std::string, but I can't reproduce it so far actually. But I feel like this is a workaround, but not the easy way to do it.
How do I create QString with value \u0000 using QString API and why QString("\u0000") results in value "\u0001"?

QString is always null-terminated. A null QString means that it has no data in its internal array but an empty QString has a single null character in its internal data array. So, if you have any control over the sender of the original array, it is better to send it by a QByteArray instead of a QString. You won't be able to count multiple null characters in a QString.
From QString reference document:
QString().isNull(); // returns true
QString().isEmpty(); // returns true
QString("").isNull(); // returns false
QString("").isEmpty(); // returns true
QString("abc").isNull(); // returns false
QString("abc").isEmpty(); // returns false

I figured out how to create such a string.
QString str(1, QChar('\0'));
or from std::string:
QString::fromStdString(std::string("\0", 1));
But I still don't know why QString("\u0000") results in "\u0001"

Related

QLocale setDefault only works at 2nd time called

I am trying to change the default language of a QLocale variable in my code and then use the different separators of each language. I do not want to change it for the whole system I just want to have a chance to print numbers with different group- and decimal separators.
The user can change the Decimal separator to what he or she prefers.
//this part works as expected in debugger
QLocale locale;
if(decSep==".")
{
locale.setDefault(QLocale::English);
}
else if(decSep==",")
{
locale.setDefault(QLocale::German);
}
else
{
locale.setDefault(QLocale::system().language());
}
//added for debug purposes
/*if(local.language()==QLocale::English)
{
int x=0;//jumped here when it was supposed to do so (decSep==".")
}*/
Now there is some code which I'm sure has nothing to do with this error.
Later I use:
//Now this doesn't work
QString tempNum1 = locale.toString(myNum, 'f');
With locale.toString I get the separators default to the given language.
Now my problem is that the locale variable seems to need some time or smth to change to other settings. When I change the decSep var and therefore the language is changed (I debugged this, this part is changed and when I ask for the language it gives the right enum) it uses the previously set settings. When I then call the function again, which gives me the tempNum1 string then it is working.
Is this a known problem or am I doing something wrong? Can I somehow updated locale or something like that?
You are setting the default locale, not the language of the current QLocale object.
Note that setDefault is a static function and therefore it does not change the object properties itself, i.e.
locale.setDefault(QLocale::English)
is the same as
QLocale::setDefault(QLocale::English)
Example
The following example may clarify this behaviour:
QLocale locale;
QLocale localeGerman(QLocale::German);
qDebug() << locale.toString(1.234, 'f'); // returns 1.234
qDebug() << localeGerman.toString(1.234, 'f'); // returns 1,234
QLocale::setDefault(QLocale::German); // same as locale.setDefault(QLocale::German);
qDebug() << locale.toString(1.234, 'f'); // returns still 1.234
QLocale locale2;
qDebug() << locale2.toString(1.234, 'f'); // returns 1,234
locale = localeGerman;
qDebug() << locale.toString(1.234, 'f'); // returns 1,234

QMetaType::convert failed

I'm trying to use QMetaType::convert to convert a QJsonValue to another dynamic type. At first, I tested the following code with the dynamic type setting to QString, the conversion was failed.
QJsonValue value("test");
QString string;
if (!QMetaType::convert(&value, QMetaType::QJsonValue, &string, QMetaType::QString))
{
qDebug() << "failed";
}
Then, I found this static method to check whether the meta system has a registered conversion between two meta types.
qDebug() << QMetaType::hasRegisteredConverterFunction(QMetaType::QJsonValue, QMetaType::QString);
unfortunately, the result was false. Maybe QJsonValue is so complex that the conversion from QJsonValue to QString is not supported. Finally, I tried this, and the result was still false:
qDebug() << QMetaType::hasRegisteredConverterFunction(QMetaType::Int, QMetaType::Int);
It's odd, seems to be, Qt dose not implement the converter functions between basic meta types. And, users can't use QMetaType::registerConverter to register converter function between two basic meta types.
I still can't believe that Qt dosen't implement conversions between basic meta types, is there any initializtion or .pro setting I missed?
I guess you have the QMetaType system and the QVariant class to encapsulate Qt data types on the one hand, and QJsonValue to encapsulate a value in JSON on the other hand.
QMetaType::convert can deal with QVariant data only. What you can do is to extract the QVariant from your QJsonValue and then use the QMetaType system to convert your data you know being a QString.
// Your code
QJsonValue value("test");
QString string ;
if (!QMetaType::convert(&value, QMetaType::QJsonValue, &string, QMetaType::QString))
{
qDebug() << "failed";
}
// Extract the QVariant data
QVariant variant = value.toVariant() ;
// Two way to test conversion between QVariant and a type
qDebug() << "canConvert template:" << variant.canConvert<QString>() << endl
<< "canConvert parameter:" << variant.canConvert( QMetaType::QString ) ;
if( variant.canConvert<QString>() )
{
// Convert using QVariant methods
qDebug() << "QVariant toString:" << variant.toString() ;
// Convert Using QJsonValue methods
qDebug() << "QJsonValue toString:" << value.toString() ; // It's just a string representation of the data, not the actual data
}
outputs :
failed
canConvert template: true
canConvert parameter: true
QVariant toString: "test"
QJsonValue toString: "test"
PS: the QJsonValue::Type : String is different from the QVariant::Type : String (QMetaType::QString) so there is no relationship between them.

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

Finding a specific character in a file in Qt

How can i find a specific character in a QFile which has a text in it?
for example i have ' $5000 ' written somewhere in my file. in want to find the "$" sign so i will realize that I've reached the number.
I tried using QString QTextStream::read(qint64 maxlen) by putting 1 as the maxlen :
QFile myfile("myfile.txt");
myfile.open(QIODevice::ReadWrite | QIODevice::Text);
QTextStream myfile_stream(&myfile);
while(! myfile_stream.atEnd())
{
if( myfile_stream.read(1) == '$')
{
qDebug()<<"found";
break;
}
}
and i get "error: invalid conversion from 'char' to 'const char* "
i also tried using the operator[] but apparently it can't be used for files.
Read in a line at a time and search the text that you've read in
QTextStream stream(&myFile);
QString line;
do
{
line = stream.readLine();
if(line.contains("$"))
{
qDebug()<<"found";
break;
}
} while (!line.isNull());
The error message you've posted doesn't match the issue in your code. Possibly the error was caused by something else.
QTextStream::read returns QString. You can't compare QString and const char* directly, but operator[] can help:
QString s = stream.read(1);
if (s.count() == 1) {
if (s[0] == '$') {
//...
}
}
However reading a file by too small pieces will be very slow. If your file is small enough, you can read it all at once:
QString s = stream.readAll();
int index = s.indexOf('$');
If your file is large, it's better to read file by small chunks (1024 bytes for example) and calculate the index of found character using indexOf result and count of already read chunks.
a single char could be read with
QTextStream myfile_stream(&myfile);
QChar c;
while (!myfile_stream.atEnd())
myfile_stream >> c;
if (c == '$') {
...
}
myfile_stream.read(1) - this is not good practice, you should not read from file one byte at a time. Either read the entire file, or buffered/line by line if there is a risk for the file to be too big to fit in memory.
The error you get is because you compare a QString for equality with a character literal - needless to say that is not going to work as expected. A string is a string even if there is only one character in it. As advised - use either the [] operator or better off for reading - QString::at() const which is guaranteed to create no extra copy. You don't use it on the QFile, nor on the QTextStream, but on the QString that is returned from the read() method of the text stream targeted at the file.
Once you have the text in memory, you can either use the regular QString methods like indexOf() to search for the index of a contained character.
in want to find the "$" sign so i will realize that I've reached the
number.
It sounds to me that you're searching for the '$' symbol because you're more interested in the dollar value that follows it. In this case, I suggest reading the files line by line and running them through a QRegExp to extract any values you're looking for.
QRegExp dollarFind("\\$(\\d+)");
while(!myfile_stream.atEnd()){
QString line = myfile_stream.readLine();
if (dollarFind.exactMatch(line)){
QStringList dollars = dollarFind.capturedTexts();
qDebug() << "Dollar values found: " << dollars.join(", ");
}
}

Qt. get part of QString

I want to get QString from another QString, when I know necessary indexes.
For example:
Main string: "This is a string".
I want to create new QString from first 5 symbols and get "This ".
input : first and last char number.
output : new QString.
How to create it ?
P.S. Not only first several letters, also from the middle of the line, for example from 5 till 8.
If you do not need to modify the substring, then you can use QStringRef. The QStringRef class is a read only wrapper around an existing QString that references a substring within the existing string. This gives much better performance than creating a new QString object to contain the sub-string. E.g.
QString myString("This is a string");
QStringRef subString(&myString, 5, 2); // subString contains "is"
If you do need to modify the substring, then left(), mid() and right() will do what you need...
QString myString("This is a string");
QString subString = myString.mid(5,2); // subString contains "is"
subString.append("n't"); // subString contains "isn't"
Use the left function:
QString yourString = "This is a string";
QString leftSide = yourString.left(5);
qDebug() << leftSide; // output "This "
Also have a look at mid() if you want more control.

Resources