问题
I have a string. For example:
QString myString = "Today is Tuesday";
The requirement is: when user types a string, if that string is contained in myString
, then that part in the myString
should be bold, and case insensitive (Qt::CaseInsensitive
), but the format of myString
should remain (upper case characters should be upper case and lower case characters should be lower case).
For example:
- user types:
tu
-> Today is Tuesday - user types:
ES
-> Today is Tuesday - user types:
aY
-> Today is Tuesday
This is my function:
void myClass::setBoldForMatching( const QString &p_text )
{
QRegExp regExp( p_text, Qt::CaseInsensitive, QRegExp::RegExp );
if ( !p_text.isEmpty() )
{
if ( myString.contains( regExp ) )
{
myString = myString.replace( p_text, QString( "<b>" + p_text + "</b>" ), Qt::CaseInsensitive );
}
}
}
This function is wrong because
user types t
-> today is tuesday.
What I need is Today is Tuesday
How should I update my function?
回答1:
We can use a different QString::replace()
, which accepts a QRexExp
, to substitute all occurrences. The key to this is that we need a capture group in order to replace the original text in the substitution, using a back-reference (\1
):
#include <QRegExp>
QString setBoldForMatching(QString haystack, const QString& needle)
{
if (needle.isEmpty()) return haystack;
const QRegExp re{"("+QRegExp::escape(needle)+")", Qt::CaseInsensitive};
return haystack.replace(re, "<b>\\1</b>");
}
Demo
#include <QDebug>
int main()
{
qInfo() << setBoldForMatching("THIS DAY (today) is Tuesday.", "Day");
}
THIS DAY (today) is Tuesday.
回答2:
Replacing a match with p_text
will always change the case to the one of p_text
. So you have to do the replacement step by step, like this:
void myClass::setBoldForMatching(const QString &p_text) {
QRegExp regExp( p_text, Qt::CaseInsensitive, QRegExp::FixedString );
QString start = "<b>";
QString stop = "</b>";
int i=-1;
while (-1 != (i=myString.indexOf(regExp,i+1))) {
myString.insert(i, start);
i += start.size();
i += p_text.size();
myString.insert(i, stop);
i += stop.size();
}
}
As you can see, with this code, the start and stop tags will be inserted before and after the match, without changing the matched sub-string itself.
Here are some test cases:
- Today is Tuesday +
tu
--> Today is Tuesday - Today is Tuesday +
ES
--> Today is Tuesday - Today is Tuesday +
aY
--> Today is Tuesday Today is Tuesday +
t
--> Today is TuesdayToday is today +
To
--> Today is today
回答3:
Solution
Change your setBoldForMatching
like this:
void myClass::setBoldForMatching(const QString &p_text)
{
QRegExp regExp(p_text, Qt::CaseInsensitive, QRegExp::RegExp);
QString str = myString;
if (p_text.isEmpty()) {
label->setText(myString);
return;
}
int count = 0;
int pos = 0;
QStringList matches;
while ((pos = regExp.indexIn(str, pos)) != -1) {
++count;
pos += regExp.matchedLength();
matches.append(regExp.capturedTexts());
}
foreach (const QString &match, matches) {
str.replace(match, "<b>" + match + "</b>");
}
}
I have decided to keep the original content of myString
, so the result is contained in str
instead.
Example
I have prepared a small example for you in order to demonstrate the result. The full code is available on GitHub.
Result
来源:https://stackoverflow.com/questions/52054261/how-to-replace-qregexp-in-a-string