想做蜗牛的蝎 發表於 2026-1-5 09:42:55

Qt中QString 查找子串的多种方法

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>1. 基本查找方法</li><ul class="second_class_ul"><li>1.1 查找子串是否存在</li><li>1.2 查找子串位置</li></ul><li>2. 查找和统计</li><ul class="second_class_ul"><li>2.1 统计子串出现次数</li><li>2.2 查找所有出现位置</li></ul><li>3. 高级查找方法</li><ul class="second_class_ul"><li>3.1 使用正则表达式查找</li><li>3.2 查找并替换</li></ul><li>4. 完整的查找工具类</li><ul class="second_class_ul"><li>4.1 StringFinder 类</li></ul><li>5. 实际应用示例</li><ul class="second_class_ul"><li>5.1 日志分析工具</li><li>5.2 文本搜索工具</li></ul><li>6. 性能优化</li><ul class="second_class_ul"><li>6.1 高效查找算法</li></ul><li>7. 完整的示例程序</li><ul class="second_class_ul"></ul><li>8. 重要注意事项</li><ul class="second_class_ul"></ul></ul></div><p>在 Qt 中,QString 提供了多种查找子串的方法。以下是详细的使用方法和示例:</p>
<p class="maodian"></p><h2>1. 基本查找方法</h2>
<p class="maodian"></p><h3>1.1 查找子串是否存在</h3>
<div class="jb51code"><pre class="brush:cpp;">#include &lt;QString&gt;
#include &lt;QDebug&gt;

void basicFindMethods()
{
    QString str = "Hello, World! This is a test string.";
   
    // 1.1 contains() - 检查是否包含子串
    bool containsHello = str.contains("Hello");
    bool containsWorld = str.contains("World");
    bool containsTest = str.contains("test");
    bool containsMissing = str.contains("missing");
   
    qDebug() &lt;&lt; "包含 'Hello':" &lt;&lt; containsHello;      // true
    qDebug() &lt;&lt; "包含 'World':" &lt;&lt; containsWorld;      // true
    qDebug() &lt;&lt; "包含 'test':" &lt;&lt; containsTest;      // true
    qDebug() &lt;&lt; "包含 'missing':" &lt;&lt; containsMissing;// false
   
    // 1.2 大小写敏感控制
    bool containsHelloCaseSensitive = str.contains("hello", Qt::CaseSensitive);
    bool containsHelloCaseInsensitive = str.contains("hello", Qt::CaseInsensitive);
   
    qDebug() &lt;&lt; "区分大小写查找 'hello':" &lt;&lt; containsHelloCaseSensitive;    // false
    qDebug() &lt;&lt; "不区分大小写查找 'hello':" &lt;&lt; containsHelloCaseInsensitive; // true
   
    // 1.3 使用正则表达式
    bool containsDigits = str.contains(QRegularExpression("\\d+"));
    bool containsWord = str.contains(QRegularExpression("\\btest\\b"));
   
    qDebug() &lt;&lt; "包含数字:" &lt;&lt; containsDigits;// false
    qDebug() &lt;&lt; "包含完整单词 'test':" &lt;&lt; containsWord;// true
}
</pre></div>
<p class="maodian"></p><h3>1.2 查找子串位置</h3>
<div class="jb51code"><pre class="brush:cpp;">void findPositions()
{
    QString str = "The quick brown fox jumps over the lazy dog. The fox is brown.";
   
    // 2.1 indexOf() - 查找第一次出现的位置
    int pos1 = str.indexOf("fox");
    int pos2 = str.indexOf("fox", 20);// 从位置20开始查找
    int pos3 = str.indexOf("cat");      // 未找到返回-1
   
    qDebug() &lt;&lt; "'fox' 第一次出现位置:" &lt;&lt; pos1;// 16
    qDebug() &lt;&lt; "从位置20开始查找 'fox':" &lt;&lt; pos2;// 44
    qDebug() &lt;&lt; "'cat' 的位置:" &lt;&lt; pos3;// -1
   
    // 2.2 lastIndexOf() - 查找最后一次出现的位置
    int lastPos1 = str.lastIndexOf("fox");
    int lastPos2 = str.lastIndexOf("fox", 30);// 在位置30之前查找
   
    qDebug() &lt;&lt; "'fox' 最后一次出现位置:" &lt;&lt; lastPos1;// 44
    qDebug() &lt;&lt; "在位置30之前查找 'fox':" &lt;&lt; lastPos2;// 16
   
    // 2.3 大小写敏感控制
    int posCaseSensitive = str.indexOf("The");
    int posCaseInsensitive = str.indexOf("the", 0, Qt::CaseInsensitive);
   
    qDebug() &lt;&lt; "区分大小写查找 'The':" &lt;&lt; posCaseSensitive;      // 0
    qDebug() &lt;&lt; "不区分大小写查找 'the':" &lt;&lt; posCaseInsensitive;// 32
}
</pre></div>
<p class="maodian"></p><h2>2. 查找和统计</h2>
<p class="maodian"></p><h3>2.1 统计子串出现次数</h3>
<div class="jb51code"><pre class="brush:cpp;">void countOccurrences()
{
    QString str = "apple banana apple orange apple grape apple";
   
    // 3.1 count() - 统计子串出现次数
    int appleCount = str.count("apple");
    int bananaCount = str.count("banana");
    int orangeCount = str.count("orange");
    int missingCount = str.count("pear");
   
    qDebug() &lt;&lt; "'apple' 出现次数:" &lt;&lt; appleCount;    // 4
    qDebug() &lt;&lt; "'banana' 出现次数:" &lt;&lt; bananaCount;// 1
    qDebug() &lt;&lt; "'orange' 出现次数:" &lt;&lt; orangeCount;// 1
    qDebug() &lt;&lt; "'pear' 出现次数:" &lt;&lt; missingCount;   // 0
   
    // 3.2 大小写敏感控制
    int appleCaseSensitive = str.count("Apple", Qt::CaseSensitive);
    int appleCaseInsensitive = str.count("Apple", Qt::CaseInsensitive);
   
    qDebug() &lt;&lt; "区分大小写统计 'Apple':" &lt;&lt; appleCaseSensitive;    // 0
    qDebug() &lt;&lt; "不区分大小写统计 'Apple':" &lt;&lt; appleCaseInsensitive; // 4
   
    // 3.3 统计字符出现次数
    int aCount = str.count('a');
    int pCount = str.count('p');
   
    qDebug() &lt;&lt; "字符 'a' 出现次数:" &lt;&lt; aCount;// 8
    qDebug() &lt;&lt; "字符 'p' 出现次数:" &lt;&lt; pCount;// 8
}
</pre></div>
<p class="maodian"></p><h3>2.2 查找所有出现位置</h3>
<div class="jb51code"><pre class="brush:cpp;">#include &lt;QVector&gt;

void findAllOccurrences()
{
    QString str = "abracadabra abra kadabra";
    QString sub = "abra";
   
    // 4.1 查找所有出现位置
    QVector&lt;int&gt; positions;
    int pos = 0;
   
    while ((pos = str.indexOf(sub, pos)) != -1) {
      positions.append(pos);
      pos += sub.length();// 移动到下一个位置
    }
   
    qDebug() &lt;&lt; "'abra' 的所有位置:";
    for (int p : positions) {
      qDebug() &lt;&lt; "位置:" &lt;&lt; p &lt;&lt; ", 子串:" &lt;&lt; str.mid(p, sub.length());
    }
   
    // 4.2 查找重叠的子串
    QString str2 = "aaaaa";
    QString sub2 = "aa";
    QVector&lt;int&gt; overlappingPositions;
   
    pos = 0;
    while ((pos = str2.indexOf(sub2, pos)) != -1) {
      overlappingPositions.append(pos);
      pos += 1;// 只移动1位,允许重叠
    }
   
    qDebug() &lt;&lt; "'aa' 在 'aaaaa' 中的所有位置(允许重叠):";
    for (int p : overlappingPositions) {
      qDebug() &lt;&lt; "位置:" &lt;&lt; p;
    }
}
</pre></div>
<p class="maodian"></p><h2>3. 高级查找方法</h2>
<p class="maodian"></p><h3>3.1 使用正则表达式查找</h3>
<div class="jb51code"><pre class="brush:cpp;">#include &lt;QRegularExpression&gt;
#include &lt;QRegularExpressionMatch&gt;

void regexFindMethods()
{
    QString str = "Email: test@example.com, Phone: 123-456-7890, Date: 2023-12-20";
   
    // 5.1 查找匹配
    QRegularExpression emailRegex(R"(\b+@+\.{2,}\b)");
    QRegularExpressionMatch emailMatch = emailRegex.match(str);
   
    if (emailMatch.hasMatch()) {
      QString email = emailMatch.captured(0);
      qDebug() &lt;&lt; "找到邮箱:" &lt;&lt; email;
      qDebug() &lt;&lt; "起始位置:" &lt;&lt; emailMatch.capturedStart();
      qDebug() &lt;&lt; "结束位置:" &lt;&lt; emailMatch.capturedEnd();
    }
   
    // 5.2 查找电话号码
    QRegularExpression phoneRegex(R"(\b\d{3}[-.]?\d{3}[-.]?\d{4}\b)");
    QRegularExpressionMatch phoneMatch = phoneRegex.match(str);
   
    if (phoneMatch.hasMatch()) {
      qDebug() &lt;&lt; "找到电话:" &lt;&lt; phoneMatch.captured(0);
    }
   
    // 5.3 查找所有匹配
    QRegularExpression dateRegex(R"(\b\d{4}-\d{2}-\d{2}\b)");
    QRegularExpressionMatchIterator dateIterator = dateRegex.globalMatch(str);
   
    qDebug() &lt;&lt; "所有日期:";
    while (dateIterator.hasNext()) {
      QRegularExpressionMatch match = dateIterator.next();
      qDebug() &lt;&lt; "" &lt;&lt; match.captured(0) &lt;&lt; "在位置" &lt;&lt; match.capturedStart();
    }
   
    // 5.4 捕获组
    QString logLine = "2023-12-20 14:30:25 User login successful";
    QRegularExpression logRegex(R"((\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}) \[(\w+)\] (.+))");
    QRegularExpressionMatch logMatch = logRegex.match(logLine);
   
    if (logMatch.hasMatch()) {
      qDebug() &lt;&lt; "日志解析:";
      qDebug() &lt;&lt; "日期:" &lt;&lt; logMatch.captured(1);
      qDebug() &lt;&lt; "时间:" &lt;&lt; logMatch.captured(2);
      qDebug() &lt;&lt; "级别:" &lt;&lt; logMatch.captured(3);
      qDebug() &lt;&lt; "消息:" &lt;&lt; logMatch.captured(4);
    }
}
</pre></div>
<p class="maodian"></p><h3>3.2 查找并替换</h3>
<div class="jb51code"><pre class="brush:cpp;">void findAndReplace()
{
    QString str = "The quick brown fox jumps over the lazy dog.";
   
    // 6.1 replace() - 简单替换
    QString replaced1 = str;
    replaced1.replace("fox", "cat");
    qDebug() &lt;&lt; "替换 'fox' 为 'cat':" &lt;&lt; replaced1;
   
    // 6.2 替换所有出现
    QString str2 = "apple apple orange apple";
    QString replaced2 = str2;
    replaced2.replace("apple", "pear");
    qDebug() &lt;&lt; "替换所有 'apple' 为 'pear':" &lt;&lt; replaced2;
   
    // 6.3 使用正则表达式替换
    QString html = "&lt;p&gt;Hello &lt;b&gt;World&lt;/b&gt;!&lt;/p&gt;";
    QRegularExpression tagRegex(R"(&lt;[^&gt;]*&gt;)");
    QString textOnly = html;
    textOnly.replace(tagRegex, "");
    qDebug() &lt;&lt; "移除HTML标签:" &lt;&lt; textOnly;
   
    // 6.4 使用lambda进行复杂替换
    QString numbers = "1, 2, 3, 4, 5";
    QRegularExpression numRegex(R"(\d+)");
    QString doubled = numbers;
    doubled.replace(numRegex, const QRegularExpressionMatch &amp;match {
      int num = match.captured(0).toInt();
      return QString::number(num * 2);
    });
    qDebug() &lt;&lt; "数字加倍:" &lt;&lt; doubled;
}
</pre></div>
<p class="maodian"></p><h2>4. 完整的查找工具类</h2>
<p class="maodian"></p><h3>4.1 StringFinder 类</h3>
<div class="jb51code"><pre class="brush:cpp;">// StringFinder.h
#ifndef STRINGFINDER_H
#define STRINGFINDER_H

#include &lt;QString&gt;
#include &lt;QVector&gt;
#include &lt;QRegularExpression&gt;
#include &lt;QPair&gt;

class StringFinder
{
public:
    // 查找单个子串的所有出现
    static QVector&lt;int&gt; findAll(const QString&amp; text,
                               const QString&amp; substring,
                               Qt::CaseSensitivity cs = Qt::CaseSensitive);
   
    // 查找多个子串的所有出现
    static QVector&lt;QPair&lt;QString, int&gt;&gt; findAllMultiple(const QString&amp; text,
                                                       const QStringList&amp; substrings,
                                                       Qt::CaseSensitivity cs = Qt::CaseSensitive);
   
    // 使用正则表达式查找
    static QVector&lt;QRegularExpressionMatch&gt; findAllRegex(const QString&amp; text,
                                                      const QRegularExpression&amp; regex);
   
    // 统计子串出现次数
    static int countOccurrences(const QString&amp; text,
                               const QString&amp; substring,
                               Qt::CaseSensitivity cs = Qt::CaseSensitive);
   
    // 查找最长的公共子串
    static QString findLongestCommonSubstring(const QString&amp; str1,
                                             const QString&amp; str2);
   
    // 查找最长的重复子串
    static QString findLongestRepeatedSubstring(const QString&amp; text);
   
    // 查找所有单词及其位置
    static QVector&lt;QPair&lt;QString, int&gt;&gt; findAllWords(const QString&amp; text);
   
    // 模糊查找(支持通配符)
    static QVector&lt;int&gt; fuzzyFind(const QString&amp; text,
                                 const QString&amp; pattern,
                                 Qt::CaseSensitivity cs = Qt::CaseSensitive);
   
    // 查找并高亮显示
    static QString highlightAll(const QString&amp; text,
                               const QString&amp; substring,
                               const QString&amp; startTag = "&lt;mark&gt;",
                               const QString&amp; endTag = "&lt;/mark&gt;",
                               Qt::CaseSensitivity cs = Qt::CaseSensitive);
   
private:
    // 计算编辑距离(用于模糊匹配)
    static int editDistance(const QString&amp; s1, const QString&amp; s2);
   
    // 构建后缀数组
    static QVector&lt;int&gt; buildSuffixArray(const QString&amp; text);
};

#endif // STRINGFINDER_H
</pre></div>
<div class="jb51code"><pre class="brush:cpp;">// StringFinder.cpp
#include "StringFinder.h"
#include &lt;QDebug&gt;
#include &lt;algorithm&gt;

QVector&lt;int&gt; StringFinder::findAll(const QString&amp; text,
                                  const QString&amp; substring,
                                  Qt::CaseSensitivity cs)
{
    QVector&lt;int&gt; positions;
   
    if (substring.isEmpty() || text.isEmpty()) {
      return positions;
    }
   
    int pos = 0;
    while ((pos = text.indexOf(substring, pos, cs)) != -1) {
      positions.append(pos);
      pos += substring.length();
    }
   
    return positions;
}

QVector&lt;QPair&lt;QString, int&gt;&gt; StringFinder::findAllMultiple(const QString&amp; text,
                                                          const QStringList&amp; substrings,
                                                          Qt::CaseSensitivity cs)
{
    QVector&lt;QPair&lt;QString, int&gt;&gt; results;
   
    for (const QString&amp; sub : substrings) {
      QVector&lt;int&gt; positions = findAll(text, sub, cs);
      for (int pos : positions) {
            results.append(qMakePair(sub, pos));
      }
    }
   
    // 按位置排序
    std::sort(results.begin(), results.end(),
            const QPair&lt;QString, int&gt;&amp; a, const QPair&lt;QString, int&gt;&amp; b {
                  return a.second &lt; b.second;
            });
   
    return results;
}

QVector&lt;QRegularExpressionMatch&gt; StringFinder::findAllRegex(const QString&amp; text,
                                                         const QRegularExpression&amp; regex)
{
    QVector&lt;QRegularExpressionMatch&gt; matches;
   
    if (!regex.isValid()) {
      qWarning() &lt;&lt; "无效的正则表达式:" &lt;&lt; regex.errorString();
      return matches;
    }
   
    QRegularExpressionMatchIterator iterator = regex.globalMatch(text);
    while (iterator.hasNext()) {
      matches.append(iterator.next());
    }
   
    return matches;
}

int StringFinder::countOccurrences(const QString&amp; text,
                                  const QString&amp; substring,
                                  Qt::CaseSensitivity cs)
{
    if (substring.isEmpty()) {
      return 0;
    }
   
    int count = 0;
    int pos = 0;
   
    while ((pos = text.indexOf(substring, pos, cs)) != -1) {
      count++;
      pos += substring.length();
    }
   
    return count;
}

QString StringFinder::findLongestCommonSubstring(const QString&amp; str1,
                                                const QString&amp; str2)
{
    int m = str1.length();
    int n = str2.length();
   
    if (m == 0 || n == 0) {
      return QString();
    }
   
    // 创建DP表
    QVector&lt;QVector&lt;int&gt;&gt; dp(m + 1, QVector&lt;int&gt;(n + 1, 0));
    int maxLength = 0;
    int endPos = 0;
   
    for (int i = 1; i &lt;= m; i++) {
      for (int j = 1; j &lt;= n; j++) {
            if (str1 == str2) {
                dp = dp + 1;
                if (dp &gt; maxLength) {
                  maxLength = dp;
                  endPos = i;
                }
            }
      }
    }
   
    if (maxLength == 0) {
      return QString();
    }
   
    return str1.mid(endPos - maxLength, maxLength);
}

QString StringFinder::findLongestRepeatedSubstring(const QString&amp; text)
{
    int n = text.length();
   
    if (n &lt; 2) {
      return QString();
    }
   
    // 构建后缀数组
    QVector&lt;int&gt; suffixArray = buildSuffixArray(text);
   
    // 查找最长公共前缀
    QString longest = "";
   
    for (int i = 0; i &lt; n - 1; i++) {
      int idx1 = suffixArray;
      int idx2 = suffixArray;
      
      // 查找公共前缀
      int k = 0;
      while (idx1 + k &lt; n &amp;&amp; idx2 + k &lt; n &amp;&amp;
               text == text) {
            k++;
      }
      
      if (k &gt; longest.length()) {
            longest = text.mid(idx1, k);
      }
    }
   
    return longest;
}

QVector&lt;QPair&lt;QString, int&gt;&gt; StringFinder::findAllWords(const QString&amp; text)
{
    QVector&lt;QPair&lt;QString, int&gt;&gt; words;
   
    QRegularExpression wordRegex(R"(\b\w+\b)");
    QRegularExpressionMatchIterator iterator = wordRegex.globalMatch(text);
   
    while (iterator.hasNext()) {
      QRegularExpressionMatch match = iterator.next();
      QString word = match.captured(0);
      int pos = match.capturedStart();
      words.append(qMakePair(word, pos));
    }
   
    return words;
}

QVector&lt;int&gt; StringFinder::fuzzyFind(const QString&amp; text,
                                    const QString&amp; pattern,
                                    Qt::CaseSensitivity cs)
{
    QVector&lt;int&gt; positions;
   
    if (pattern.isEmpty() || text.isEmpty()) {
      return positions;
    }
   
    QString patternLower = (cs == Qt::CaseInsensitive) ? pattern.toLower() : pattern;
    QString textLower = (cs == Qt::CaseInsensitive) ? text.toLower() : text;
   
    // 简单的模糊匹配:检查是否包含所有字符(按顺序)
    for (int i = 0; i &lt;= text.length() - pattern.length(); i++) {
      bool found = true;
      int patternIndex = 0;
      
      for (int j = i; j &lt; text.length() &amp;&amp; patternIndex &lt; pattern.length(); j++) {
            if (textLower == patternLower) {
                patternIndex++;
            }
      }
      
      if (patternIndex == pattern.length()) {
            positions.append(i);
      }
    }
   
    return positions;
}

QString StringFinder::highlightAll(const QString&amp; text,
                                  const QString&amp; substring,
                                  const QString&amp; startTag,
                                  const QString&amp; endTag,
                                  Qt::CaseSensitivity cs)
{
    if (substring.isEmpty()) {
      return text;
    }
   
    QString result = text;
    QVector&lt;int&gt; positions = findAll(text, substring, cs);
   
    // 从后往前插入标签,避免位置偏移
    for (int i = positions.size() - 1; i &gt;= 0; i--) {
      int pos = positions;
      result.insert(pos + substring.length(), endTag);
      result.insert(pos, startTag);
    }
   
    return result;
}

int StringFinder::editDistance(const QString&amp; s1, const QString&amp; s2)
{
    int m = s1.length();
    int n = s2.length();
   
    QVector&lt;QVector&lt;int&gt;&gt; dp(m + 1, QVector&lt;int&gt;(n + 1));
   
    for (int i = 0; i &lt;= m; i++) {
      dp = i;
    }
    for (int j = 0; j &lt;= n; j++) {
      dp = j;
    }
   
    for (int i = 1; i &lt;= m; i++) {
      for (int j = 1; j &lt;= n; j++) {
            if (s1 == s2) {
                dp = dp;
            } else {
                dp = 1 + qMin(qMin(dp, dp), dp);
            }
      }
    }
   
    return dp;
}

QVector&lt;int&gt; StringFinder::buildSuffixArray(const QString&amp; text)
{
    int n = text.length();
    QVector&lt;int&gt; suffixArray(n);
   
    // 初始化后缀数组
    for (int i = 0; i &lt; n; i++) {
      suffixArray = i;
    }
   
    // 简单排序(对于大文本,应使用更高效的算法)
    std::sort(suffixArray.begin(), suffixArray.end(),
            int a, int b {
                  return text.mid(a) &lt; text.mid(b);
            });
   
    return suffixArray;
}
</pre></div>
<p class="maodian"></p><h2>5. 实际应用示例</h2>
<p class="maodian"></p><h3>5.1 日志分析工具</h3>
<div class="jb51code"><pre class="brush:cpp;">#include "StringFinder.h"
#include &lt;QFile&gt;
#include &lt;QTextStream&gt;
#include &lt;QDateTime&gt;

class LogAnalyzer
{
public:
    struct LogEntry {
      QDateTime timestamp;
      QString level;
      QString message;
      int lineNumber;
    };
   
    QVector&lt;LogEntry&gt; parseLogFile(const QString&amp; filePath)
    {
      QVector&lt;LogEntry&gt; entries;
      
      QFile file(filePath);
      if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
            qWarning() &lt;&lt; "无法打开日志文件:" &lt;&lt; filePath;
            return entries;
      }
      
      QTextStream in(&amp;file);
      int lineNumber = 0;
      
      // 日志格式: Message here
      QRegularExpression logRegex(R"(\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] \[(\w+)\] (.+))");
      
      while (!in.atEnd()) {
            QString line = in.readLine();
            lineNumber++;
            
            QRegularExpressionMatch match = logRegex.match(line);
            if (match.hasMatch()) {
                LogEntry entry;
                entry.timestamp = QDateTime::fromString(match.captured(1), "yyyy-MM-dd HH:mm:ss");
                entry.level = match.captured(2);
                entry.message = match.captured(3);
                entry.lineNumber = lineNumber;
               
                entries.append(entry);
            }
      }
      
      file.close();
      return entries;
    }
   
    QVector&lt;LogEntry&gt; searchInLogs(const QVector&lt;LogEntry&gt;&amp; entries,
                                  const QString&amp; searchTerm,
                                  Qt::CaseSensitivity cs = Qt::CaseInsensitive)
    {
      QVector&lt;LogEntry&gt; results;
      
      for (const LogEntry&amp; entry : entries) {
            if (entry.message.contains(searchTerm, cs) ||
                entry.level.contains(searchTerm, cs)) {
                results.append(entry);
            }
      }
      
      return results;
    }
   
    QVector&lt;LogEntry&gt; searchByRegex(const QVector&lt;LogEntry&gt;&amp; entries,
                                 const QRegularExpression&amp; regex)
    {
      QVector&lt;LogEntry&gt; results;
      
      for (const LogEntry&amp; entry : entries) {
            if (regex.match(entry.message).hasMatch() ||
                regex.match(entry.level).hasMatch()) {
                results.append(entry);
            }
      }
      
      return results;
    }
   
    QMap&lt;QString, int&gt; countByLevel(const QVector&lt;LogEntry&gt;&amp; entries)
    {
      QMap&lt;QString, int&gt; counts;
      
      for (const LogEntry&amp; entry : entries) {
            counts++;
      }
      
      return counts;
    }
};
</pre></div>
<p class="maodian"></p><h3>5.2 文本搜索工具</h3>
<div class="jb51code"><pre class="brush:cpp;">class TextSearchTool
{
public:
    struct SearchResult {
      int lineNumber;
      int position;
      QString line;
      QString matchedText;
    };
   
    QVector&lt;SearchResult&gt; searchInFile(const QString&amp; filePath,
                                    const QString&amp; searchTerm,
                                    Qt::CaseSensitivity cs = Qt::CaseSensitive)
    {
      QVector&lt;SearchResult&gt; results;
      
      QFile file(filePath);
      if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
            return results;
      }
      
      QTextStream in(&amp;file);
      int lineNumber = 0;
      
      while (!in.atEnd()) {
            QString line = in.readLine();
            lineNumber++;
            
            int pos = 0;
            while ((pos = line.indexOf(searchTerm, pos, cs)) != -1) {
                SearchResult result;
                result.lineNumber = lineNumber;
                result.position = pos;
                result.line = line;
                result.matchedText = searchTerm;
               
                results.append(result);
               
                pos += searchTerm.length();
            }
      }
      
      file.close();
      return results;
    }
   
    QVector&lt;SearchResult&gt; searchWithRegex(const QString&amp; filePath,
                                       const QRegularExpression&amp; regex)
    {
      QVector&lt;SearchResult&gt; results;
      
      QFile file(filePath);
      if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
            return results;
      }
      
      QTextStream in(&amp;file);
      int lineNumber = 0;
      
      while (!in.atEnd()) {
            QString line = in.readLine();
            lineNumber++;
            
            QRegularExpressionMatchIterator iterator = regex.globalMatch(line);
            while (iterator.hasNext()) {
                QRegularExpressionMatch match = iterator.next();
               
                SearchResult result;
                result.lineNumber = lineNumber;
                result.position = match.capturedStart();
                result.line = line;
                result.matchedText = match.captured();
               
                results.append(result);
            }
      }
      
      file.close();
      return results;
    }
   
    QString highlightMatches(const QString&amp; text,
                            const QVector&lt;SearchResult&gt;&amp; results,
                            const QString&amp; startTag = "&lt;span style='background-color: yellow;'&gt;",
                            const QString&amp; endTag = "&lt;/span&gt;")
    {
      QString highlighted = text;
      
      // 从后往前插入标签,避免位置偏移
      for (int i = results.size() - 1; i &gt;= 0; i--) {
            const SearchResult&amp; result = results;
            highlighted.insert(result.position + result.matchedText.length(), endTag);
            highlighted.insert(result.position, startTag);
      }
      
      return highlighted;
    }
};
</pre></div>
<p class="maodian"></p><h2>6. 性能优化</h2>
<p class="maodian"></p><h3>6.1 高效查找算法</h3>
<div class="jb51code"><pre class="brush:cpp;">#include &lt;QHash&gt;
#include &lt;QSet&gt;

class EfficientStringSearcher
{
public:
    // Boyer-Moore算法实现
    static QVector&lt;int&gt; boyerMooreSearch(const QString&amp; text,
                                        const QString&amp; pattern,
                                        Qt::CaseSensitivity cs = Qt::CaseSensitive)
    {
      QVector&lt;int&gt; positions;
      
      int n = text.length();
      int m = pattern.length();
      
      if (m == 0 || n == 0 || m &gt; n) {
            return positions;
      }
      
      // 预处理坏字符表
      QHash&lt;QChar, int&gt; badChar;
      for (int i = 0; i &lt; m - 1; i++) {
            badChar] = m - 1 - i;
      }
      
      // 搜索
      int s = 0;
      while (s &lt;= n - m) {
            int j = m - 1;
            
            // 从右向左比较
            while (j &gt;= 0) {
                QChar textChar = (cs == Qt::CaseInsensitive) ?
                                 text.toLower() : text;
                QChar patternChar = (cs == Qt::CaseInsensitive) ?
                                 pattern.toLower() : pattern;
               
                if (textChar != patternChar) {
                  break;
                }
                j--;
            }
            
            if (j &lt; 0) {
                // 找到匹配
                positions.append(s);
                s += (s + m &lt; n) ? badChar.value(text, m) : 1;
            } else {
                // 根据坏字符规则移动
                QChar badCharValue = (cs == Qt::CaseInsensitive) ?
                                    text.toLower() : text;
                int shift = badChar.value(badCharValue, m);
                s += qMax(1, shift - (m - 1 - j));
            }
      }
      
      return positions;
    }
   
    // KMP算法实现
    static QVector&lt;int&gt; kmpSearch(const QString&amp; text,
                                 const QString&amp; pattern,
                                 Qt::CaseSensitivity cs = Qt::CaseSensitive)
    {
      QVector&lt;int&gt; positions;
      
      int n = text.length();
      int m = pattern.length();
      
      if (m == 0 || n == 0 || m &gt; n) {
            return positions;
      }
      
      // 构建部分匹配表
      QVector&lt;int&gt; lps(m, 0);
      int len = 0;
      int i = 1;
      
      while (i &lt; m) {
            QChar c1 = (cs == Qt::CaseInsensitive) ? pattern.toLower() : pattern;
            QChar c2 = (cs == Qt::CaseInsensitive) ? pattern.toLower() : pattern;
            
            if (c1 == c2) {
                len++;
                lps = len;
                i++;
            } else {
                if (len != 0) {
                  len = lps;
                } else {
                  lps = 0;
                  i++;
                }
            }
      }
      
      // 搜索
      i = 0;// text的索引
      int j = 0;// pattern的索引
      
      while (i &lt; n) {
            QChar textChar = (cs == Qt::CaseInsensitive) ? text.toLower() : text;
            QChar patternChar = (cs == Qt::CaseInsensitive) ? pattern.toLower() : pattern;
            
            if (textChar == patternChar) {
                i++;
                j++;
            }
            
            if (j == m) {
                // 找到匹配
                positions.append(i - j);
                j = lps;
            } else if (i &lt; n &amp;&amp; textChar != patternChar) {
                if (j != 0) {
                  j = lps;
                } else {
                  i++;
                }
            }
      }
      
      return positions;
    }
   
    // 多模式搜索(Aho-Corasick算法)
    class AhoCorasick
    {
    public:
      struct Node {
            QHash&lt;QChar, int&gt; next;
            int fail = 0;
            QVector&lt;int&gt; output;
      };
      
      AhoCorasick() {
            nodes.append(Node());// 根节点
      }
      
      void addPattern(const QString&amp; pattern, int patternId) {
            int current = 0;
            
            for (QChar ch : pattern) {
                if (!nodes.next.contains(ch)) {
                  nodes.next = nodes.size();
                  nodes.append(Node());
                }
                current = nodes.next;
            }
            
            nodes.output.append(patternId);
      }
      
      void buildFailureLinks() {
            QQueue&lt;int&gt; queue;
            
            // 第一层的失败链接指向根节点
            for (auto it = nodes.next.begin(); it != nodes.next.end(); ++it) {
                int nextNode = it.value();
                nodes.fail = 0;
                queue.enqueue(nextNode);
            }
            
            while (!queue.isEmpty()) {
                int current = queue.dequeue();
               
                for (auto it = nodes.next.begin(); it != nodes.next.end(); ++it) {
                  QChar ch = it.key();
                  int child = it.value();
                  
                  int fail = nodes.fail;
                  while (fail != 0 &amp;&amp; !nodes.next.contains(ch)) {
                        fail = nodes.fail;
                  }
                  
                  if (nodes.next.contains(ch)) {
                        nodes.fail = nodes.next;
                  } else {
                        nodes.fail = 0;
                  }
                  
                  // 合并输出
                  nodes.output.append(nodes.fail].output);
                  
                  queue.enqueue(child);
                }
            }
      }
      
      QHash&lt;int, QVector&lt;int&gt;&gt; search(const QString&amp; text) {
            QHash&lt;int, QVector&lt;int&gt;&gt; results;
            int current = 0;
            
            for (int i = 0; i &lt; text.length(); i++) {
                QChar ch = text;
               
                while (current != 0 &amp;&amp; !nodes.next.contains(ch)) {
                  current = nodes.fail;
                }
               
                if (nodes.next.contains(ch)) {
                  current = nodes.next;
                } else {
                  current = 0;
                }
               
                for (int patternId : nodes.output) {
                  results.append(i);
                }
            }
            
            return results;
      }
      
    private:
      QVector&lt;Node&gt; nodes;
    };
};
</pre></div>
<p class="maodian"></p><h2>7. 完整的示例程序</h2>
<div class="jb51code"><pre class="brush:cpp;">// main.cpp
#include &lt;QCoreApplication&gt;
#include &lt;QDebug&gt;
#include "StringFinder.h"
#include "EfficientStringSearcher.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
   
    qDebug() &lt;&lt; "=== QString 查找子串示例 ===";
   
    // 示例1: 基本查找
    {
      qDebug() &lt;&lt; "\n1. 基本查找示例:";
      QString text = "The quick brown fox jumps over the lazy dog.";
      
      qDebug() &lt;&lt; "文本:" &lt;&lt; text;
      qDebug() &lt;&lt; "包含 'fox':" &lt;&lt; text.contains("fox");
      qDebug() &lt;&lt; "'fox' 位置:" &lt;&lt; text.indexOf("fox");
      qDebug() &lt;&lt; "'the' 最后位置:" &lt;&lt; text.lastIndexOf("the");
    }
   
    // 示例2: 使用StringFinder
    {
      qDebug() &lt;&lt; "\n2. 使用StringFinder:";
      QString text = "apple banana apple orange apple";
      
      QVector&lt;int&gt; positions = StringFinder::findAll(text, "apple");
      qDebug() &lt;&lt; "'apple' 所有位置:" &lt;&lt; positions;
      
      int count = StringFinder::countOccurrences(text, "apple");
      qDebug() &lt;&lt; "'apple' 出现次数:" &lt;&lt; count;
      
      QString highlighted = StringFinder::highlightAll(text, "apple", "[", "]");
      qDebug() &lt;&lt; "高亮显示:" &lt;&lt; highlighted;
    }
   
    // 示例3: 正则表达式查找
    {
      qDebug() &lt;&lt; "\n3. 正则表达式查找:";
      QString text = "Email: test@example.com, Phone: 123-456-7890";
      
      QRegularExpression emailRegex(R"(\b\w+@\w+\.\w+\b)");
      QRegularExpressionMatch match = emailRegex.match(text);
      
      if (match.hasMatch()) {
            qDebug() &lt;&lt; "找到邮箱:" &lt;&lt; match.captured(0);
      }
      
      QRegularExpression phoneRegex(R"(\d{3}-\d{3}-\d{4})");
      match = phoneRegex.match(text);
      
      if (match.hasMatch()) {
            qDebug() &lt;&lt; "找到电话:" &lt;&lt; match.captured(0);
      }
    }
   
    // 示例4: 高效算法比较
    {
      qDebug() &lt;&lt; "\n4. 高效算法比较:";
      QString text = QString(10000, 'a') + "b" + QString(10000, 'a');
      QString pattern = "aaaab";
      
      // 普通查找
      auto start = std::chrono::high_resolution_clock::now();
      QVector&lt;int&gt; naivePositions = StringFinder::findAll(text, pattern);
      auto end = std::chrono::high_resolution_clock::now();
      auto naiveTime = std::chrono::duration_cast&lt;std::chrono::microseconds&gt;(end - start).count();
      
      // KMP算法
      start = std::chrono::high_resolution_clock::now();
      QVector&lt;int&gt; kmpPositions = EfficientStringSearcher::kmpSearch(text, pattern);
      end = std::chrono::high_resolution_clock::now();
      auto kmpTime = std::chrono::duration_cast&lt;std::chrono::microseconds&gt;(end - start).count();
      
      // Boyer-Moore算法
      start = std::chrono::high_resolution_clock::now();
      QVector&lt;int&gt; bmPositions = EfficientStringSearcher::boyerMooreSearch(text, pattern);
      end = std::chrono::high_resolution_clock::now();
      auto bmTime = std::chrono::duration_cast&lt;std::chrono::microseconds&gt;(end - start).count();
      
      qDebug() &lt;&lt; "朴素算法时间:" &lt;&lt; naiveTime &lt;&lt; "微秒";
      qDebug() &lt;&lt; "KMP算法时间:" &lt;&lt; kmpTime &lt;&lt; "微秒";
      qDebug() &lt;&lt; "Boyer-Moore算法时间:" &lt;&lt; bmTime &lt;&lt; "微秒";
      qDebug() &lt;&lt; "找到的位置数量:" &lt;&lt; naivePositions.size();
    }
   
    // 示例5: 多模式搜索
    {
      qDebug() &lt;&lt; "\n5. 多模式搜索(Aho-Corasick):";
      
      EfficientStringSearcher::AhoCorasick ac;
      
      // 添加模式
      ac.addPattern("he", 0);
      ac.addPattern("she", 1);
      ac.addPattern("his", 2);
      ac.addPattern("hers", 3);
      
      ac.buildFailureLinks();
      
      QString text = "ushers";
      auto results = ac.search(text);
      
      qDebug() &lt;&lt; "在 '" &lt;&lt; text &lt;&lt; "' 中找到的模式:";
      for (auto it = results.begin(); it != results.end(); ++it) {
            QString pattern;
            switch (it.key()) {
            case 0: pattern = "he"; break;
            case 1: pattern = "she"; break;
            case 2: pattern = "his"; break;
            case 3: pattern = "hers"; break;
            }
            
            qDebug() &lt;&lt; "模式 '" &lt;&lt; pattern &lt;&lt; "' 在位置:" &lt;&lt; it.value();
      }
    }
   
    return 0;
}
</pre></div>
<p class="maodian"></p><h2>8. 重要注意事项</h2>
<ol><li><p><strong>性能考虑</strong>:</p>
<ul><li>对于小文本,使用简单的 <code>indexOf()</code> 足够</li><li>对于大文本或频繁搜索,考虑使用高效算法</li><li>避免在循环中重复编译正则表达式</li></ul></li><li><p><strong>编码问题</strong>:</p>
<ul><li>确保文本编码正确</li><li>处理多字节字符</li><li>注意大小写敏感设置</li></ul></li><li><p><strong>内存管理</strong>:</p>
<ul><li>避免创建不必要的临时字符串</li><li>使用引用传递大字符串</li><li>及时释放不需要的内存</li></ul></li><li><p><strong>错误处理</strong>:</p>
<ul><li>检查查找结果(-1表示未找到)</li><li>验证正则表达式的有效性</li><li>处理空字符串和边界情况</li></ul></li><li><p><strong>国际化</strong>:</p>
<ul><li>考虑不同语言的文本处理</li><li>处理Unicode字符</li><li>注意区域设置</li></ul></li></ol>
<p>通过上述方法,您可以在Qt中高效地查找和处理子串。根据具体需求选择合适的查找方法和算法。更多相关Qt QString 查找子串内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>QT中QStringListModel类的应用介绍</li><li>Qt中const QString转换 char *可能的坑</li><li>QT&nbsp;中文乱码解决汇总(QString与string、char*互转乱码)</li><li>Qt中QStringList与QString的常用方法总结</li><li>Qt开发之QString类的使用教程详解</li><li>Qt QString的使用实现</li><li>Qt基础开发之QString与QByteArray详细用法与区别及QString QByteArray互转</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: Qt中QString 查找子串的多种方法