How to split QString and keep the separator in Qt? - qt

I have a QString: "{x, c | 0x01}", and I want to split it to 7 tokens as below:
{
x
,
c
|
0x01
}
What's the best way to do it in Qt?
I tried to use QString::split(QRegExp("[\\{\\},|]")), but it DOES NOT keep the separator in the result.

Maybe this solution can serve you task:
int main(void) {
QString str { "{x, c | 0x01}" };
QRegExp separators { "[\\{\\},|]" };
QStringList list;
str.replace( " ", "" );
int mem = 0;
for(int i = 0; i<str.size(); ++i) {
if(i == str.indexOf(separators, i)) {
if(mem) list.append(str.mid(mem, i-mem)); // append str before separator
list.append(str.mid(i, 1)); // append separator
mem = i+1;
}
}
qDebug() << list;
return 0;
}
Outputs: ("{", "x", ",", "c", "|", "0x01", "}")
You can eliminate if(mem) but then use list.pop_front(); orlist.removeAll(""); after the for cycle, as first element will be a rubbish "".

Basically, you iterate through the string, check if a deliminator is found, and add the deliminator to the list. If no deliminator is found, a new 'word' is added to the list, and until the next deliminator is found, characters will be added to the word. Take a look:
//input string
QString str = "{x, c | 0x01}";
QList<QString> out;
//flag used to keep track of whether we're adding a mullti-char word, or just a deliminator
bool insideWord = false;
//remove whitespaces
str = str.simplified();
str = str.replace(" ", "");
//iterate through string, check for delims, populate out list
for (int i = 0; i < str.length(); i++)
{
QChar c = str.at(i); //get char at current index
if (c == '{' || c == '}' || c == ',' || c == '|')
{
//append deliminator
out.append(c);
insideWord = false;
}
else
{
//append new word to qlist...
if (!insideWord)
{
out.append(c);
insideWord = true;
}
//but if word already started
else
{
//add 'c' to the word in last index of the qlist
out.last().append(c);
}
}
}
//output as requested by OP
qDebug() << "String is" << out;

This can be done in a single regular expression, but has to use look-ahead and look-behind.
The expression specified in the question ([\\{\\},|]) will match a 1-character long string consisting of any of the characters {, }, , or |. QString.split will then remove that 1-character long string.
What is needed is to find the zero-character string immediately before each of those separators, using a look-ahead: (?=[\\{\\},|]) and also to find the zero-character string immediately after the separator (?<=[\\{\\},|]).
Combining these gives:
QString::split(QRegularExpression("(?=[\\{\\},|])|(?<=[\\{\\},|])"))
Which will give the desired output: ("{", "x", ",", "c", "|", "0x01", "}")

Related

Store data in a vector o vectors from a txt of different lines

I am trying to read data from a file of 12 cols and 4 rows so they keep their indexes when I read them into a loop, say vec[i][j] will be i= 0...3 and j= 0...11. But the code I already have gives me a single "row", so i goes from 0 to 47. How can I fix it?
vector<vector<float>> reading(string filename) {
vector<vector<float>> vec;
ifstream file_in(filename);
if (!file_in) { cout << "File not opened" << endl; }
string line;
while (getline(file_in, line, ',')) {
vec.push_back(vector<float>());
stringstream split(line);
float value;
while (split >> value) {
vec.back().push_back(value);
}
}
return vec;
}

how to split a string into words in arduino?

I have a string in arduino
String name="apple orange banana";
Is it possible to store each item in an array arr
so that
arr[0]="apple"
arr[1]="orange" ......etc
if not store them in individual variables?
How to split a string using a specific delimiter in Arduino? I believe this would help you, you could do a while loop like:
int x;
String words[3];
while(getValue(name, ' ', x) != NULL){
words[x] = getValue(name, ' ', x);
}
Using this function:
// https://stackoverflow.com/questions/9072320/split-string-into-string-array
String getValue(String data, char separator, int index)
{
int found = 0;
int strIndex[] = {0, -1};
int maxIndex = data.length()-1;
for(int i=0; i<=maxIndex && found<=index; i++){
if(data.charAt(i)==separator || i==maxIndex){
found++;
strIndex[0] = strIndex[1]+1;
strIndex[1] = (i == maxIndex) ? i+1 : i;
}
}
return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}
If you know your list length and the max characters per list item, you could do
char arr[3][6] = {"apple", "orange", banana"};
edit: if you are looking for something like String arr[3] you aren't going to get it because of how memory is managed with the C language

Converted hex formats

I have a hex value that is in the format:
0x00000000:0x00000000:0x00000000:0x00000000
I need to convert it to a format like:
00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
I was hoping to be able to strip the 0x's and insert colons every two characters but that does not seem to be correct. How can I convert these two formats?
You can do this entirely with strings. In C#:
string original = "0x00000000:0x00000000:0x00000000:0x00000000";
//remove the unwanted characters
string[] split = { "0x", ":" };
split = original.Split(split, StringSplitOptions.RemoveEmptyEntries);
//format the rest in 2-char chunks
string result = "";
for (int i = 0; i < split.Length; i++)
{
for (int j = 0; j < split[i].Length; j += 2)
{
result += split[i].Substring(j, 2) + ":";
}
}
//remove the trailing ':'
result = result.Substring(0, result.Length - 1);
Error handling omitted for clarity.
Is this helpful?

Solving QT's QString arg() ambiguity

There is an issue using QString::arg() when a string contains a digit right after a place marker. It's not clear from the QString::arg() function description what would happen in case of such a replacement:
QString("String for replacement %1234").arg("blah");
Will this result in "String for replacement blah234" or "String for replacement blah34"?
I looked in the QT's source code to answer this question. It seems that the algorithm which looks for place markers is 'greedy' and it would take both digits in the example above.
Here is the source of the QT's function which is used inside the QString::arg() (QT 4.8.4):
static ArgEscapeData findArgEscapes(const QString &s)
{
const QChar *uc_begin = s.unicode();
const QChar *uc_end = uc_begin + s.length();
ArgEscapeData d;
d.min_escape = INT_MAX;
d.occurrences = 0;
d.escape_len = 0;
d.locale_occurrences = 0;
const QChar *c = uc_begin;
while (c != uc_end) {
while (c != uc_end && c->unicode() != '%')
++c;
if (c == uc_end)
break;
const QChar *escape_start = c;
if (++c == uc_end)
break;
bool locale_arg = false;
if (c->unicode() == 'L') {
locale_arg = true;
if (++c == uc_end)
break;
}
if (c->digitValue() == -1)
continue;
int escape = c->digitValue();
++c;
if (c != uc_end && c->digitValue() != -1) {
escape = (10 * escape) + c->digitValue();
++c;
}
if (escape > d.min_escape)
continue;
if (escape < d.min_escape) {
d.min_escape = escape;
d.occurrences = 0;
d.escape_len = 0;
d.locale_occurrences = 0;
}
++d.occurrences;
if (locale_arg)
++d.locale_occurrences;
d.escape_len += c - escape_start;
}
return d;
}
Is there a better way of solving such an ambiguity than always using a 2-digit place markers?
Since you can only use %1 to %99 as markers and you can skip marker numbers you can write:
QString("String for replacement %10234").arg("blah");
to output String for replacement blah234
Qt help states for arg(const QString & a, int fieldWidth = 0, QChar fillChar = QLatin1Char( ' ' ))
Returns a copy of this string with the lowest numbered place marker replaced by string a, i.e., %1, %2, ..., %99.
...
Place marker numbers must be in the range 1 to 99.
Therefore, what you're seeing is, by definition, correct; the first two numbers will be replaced. If you're wanting "String for replacement blah234", then you could define the string as: -
QString("String for replacement %1%2").arg("blah").arg(234);
I have the same issue, but the order answers not looks like a good way for me.
I have resolve the ambiguity in this way.
QString myString= QString("ConcatenatedNumbers%0123").arg(66,3,10, QChar('0'));
The string will be:
ConcatenatedNumbers06623

How can I partition a QByteArray efficiently?

I want to partition a QByteArray message efficiently, so this function I implemented take the Bytes, the part I want to extract, and toEnd flag which tells if I want to extract part1 till the end of the array. my dilimeter is spcae ' '
example if I have:
ba = "HELLO HOW ARE YOU?"
ba1 = getPart(ba, 1, false) -> ba1 = "HELLO"
ba2 = getPart(ba, 2, true) -> ba2 = "HOW ARE YOU?"
ba3 = getPart(ba, 3, false) -> ba3 = "ARE"
the function below works just fine, but I am wondering if this is efficient. should I consider using split function?
QByteArray Server::getPart(const QByteArray message, int part, bool toEnd)
{
QByteArray string;
int startsFrom = 0;
int endsAt = 0;
int count = 0;
for(int i = 0; i < message.size(); i++)
{
if(message.at(i) == ' ')
{
count++;
if(part == count)
{
endsAt = i;
break;
}
string.clear();
startsFrom = i + 1;
}
string.append(message.at(i));
}
if(toEnd)
{
for(int i = endsAt; i < message.size(); i++)
{
string.append(message.at(i));
}
}
return string;
}
What about this:
QByteArray Server::getPart(const QByteArray& message, int part, bool toEnd)
{
int characters(toEnd ? -1 : message.indexOf(' ', part) - part);
return message.mid(part, characters);
}
Why not make it a regular QString and use split. That will give you a QStringList.

Resources