Qt中QString 查找子串的完整指南
本文详细介绍了Qt中QString查找子串的各种方法,包括:1. 基本查找方法如contains()检查子串存在、indexOf()查找位置;2. 统计子串出现次数的count()方法;3. 高级正则表达式查找。涵盖大小写敏感控制、重叠查找等场景,提供完整代码示例,是Qt字符串处理的实用指南。
·
文章目录
Qt QString 查找子串的完整指南
在 Qt 中,QString 提供了多种查找子串的方法。以下是详细的使用方法和示例:
1. 基本查找方法
1.1 查找子串是否存在
#include <QString>
#include <QDebug>
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() << "包含 'Hello':" << containsHello; // true
qDebug() << "包含 'World':" << containsWorld; // true
qDebug() << "包含 'test':" << containsTest; // true
qDebug() << "包含 'missing':" << containsMissing; // false
// 1.2 大小写敏感控制
bool containsHelloCaseSensitive = str.contains("hello", Qt::CaseSensitive);
bool containsHelloCaseInsensitive = str.contains("hello", Qt::CaseInsensitive);
qDebug() << "区分大小写查找 'hello':" << containsHelloCaseSensitive; // false
qDebug() << "不区分大小写查找 'hello':" << containsHelloCaseInsensitive; // true
// 1.3 使用正则表达式
bool containsDigits = str.contains(QRegularExpression("\\d+"));
bool containsWord = str.contains(QRegularExpression("\\btest\\b"));
qDebug() << "包含数字:" << containsDigits; // false
qDebug() << "包含完整单词 'test':" << containsWord; // true
}
1.2 查找子串位置
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() << "'fox' 第一次出现位置:" << pos1; // 16
qDebug() << "从位置20开始查找 'fox':" << pos2; // 44
qDebug() << "'cat' 的位置:" << pos3; // -1
// 2.2 lastIndexOf() - 查找最后一次出现的位置
int lastPos1 = str.lastIndexOf("fox");
int lastPos2 = str.lastIndexOf("fox", 30); // 在位置30之前查找
qDebug() << "'fox' 最后一次出现位置:" << lastPos1; // 44
qDebug() << "在位置30之前查找 'fox':" << lastPos2; // 16
// 2.3 大小写敏感控制
int posCaseSensitive = str.indexOf("The");
int posCaseInsensitive = str.indexOf("the", 0, Qt::CaseInsensitive);
qDebug() << "区分大小写查找 'The':" << posCaseSensitive; // 0
qDebug() << "不区分大小写查找 'the':" << posCaseInsensitive; // 32
}
2. 查找和统计
2.1 统计子串出现次数
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() << "'apple' 出现次数:" << appleCount; // 4
qDebug() << "'banana' 出现次数:" << bananaCount; // 1
qDebug() << "'orange' 出现次数:" << orangeCount; // 1
qDebug() << "'pear' 出现次数:" << missingCount; // 0
// 3.2 大小写敏感控制
int appleCaseSensitive = str.count("Apple", Qt::CaseSensitive);
int appleCaseInsensitive = str.count("Apple", Qt::CaseInsensitive);
qDebug() << "区分大小写统计 'Apple':" << appleCaseSensitive; // 0
qDebug() << "不区分大小写统计 'Apple':" << appleCaseInsensitive; // 4
// 3.3 统计字符出现次数
int aCount = str.count('a');
int pCount = str.count('p');
qDebug() << "字符 'a' 出现次数:" << aCount; // 8
qDebug() << "字符 'p' 出现次数:" << pCount; // 8
}
2.2 查找所有出现位置
#include <QVector>
void findAllOccurrences()
{
QString str = "abracadabra abra kadabra";
QString sub = "abra";
// 4.1 查找所有出现位置
QVector<int> positions;
int pos = 0;
while ((pos = str.indexOf(sub, pos)) != -1) {
positions.append(pos);
pos += sub.length(); // 移动到下一个位置
}
qDebug() << "'abra' 的所有位置:";
for (int p : positions) {
qDebug() << " 位置:" << p << ", 子串:" << str.mid(p, sub.length());
}
// 4.2 查找重叠的子串
QString str2 = "aaaaa";
QString sub2 = "aa";
QVector<int> overlappingPositions;
pos = 0;
while ((pos = str2.indexOf(sub2, pos)) != -1) {
overlappingPositions.append(pos);
pos += 1; // 只移动1位,允许重叠
}
qDebug() << "'aa' 在 'aaaaa' 中的所有位置(允许重叠):";
for (int p : overlappingPositions) {
qDebug() << " 位置:" << p;
}
}
3. 高级查找方法
3.1 使用正则表达式查找
#include <QRegularExpression>
#include <QRegularExpressionMatch>
void regexFindMethods()
{
QString str = "Email: test@example.com, Phone: 123-456-7890, Date: 2023-12-20";
// 5.1 查找匹配
QRegularExpression emailRegex(R"(\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b)");
QRegularExpressionMatch emailMatch = emailRegex.match(str);
if (emailMatch.hasMatch()) {
QString email = emailMatch.captured(0);
qDebug() << "找到邮箱:" << email;
qDebug() << "起始位置:" << emailMatch.capturedStart();
qDebug() << "结束位置:" << emailMatch.capturedEnd();
}
// 5.2 查找电话号码
QRegularExpression phoneRegex(R"(\b\d{3}[-.]?\d{3}[-.]?\d{4}\b)");
QRegularExpressionMatch phoneMatch = phoneRegex.match(str);
if (phoneMatch.hasMatch()) {
qDebug() << "找到电话:" << phoneMatch.captured(0);
}
// 5.3 查找所有匹配
QRegularExpression dateRegex(R"(\b\d{4}-\d{2}-\d{2}\b)");
QRegularExpressionMatchIterator dateIterator = dateRegex.globalMatch(str);
qDebug() << "所有日期:";
while (dateIterator.hasNext()) {
QRegularExpressionMatch match = dateIterator.next();
qDebug() << " " << match.captured(0) << "在位置" << match.capturedStart();
}
// 5.4 捕获组
QString logLine = "2023-12-20 14:30:25 [INFO] 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() << "日志解析:";
qDebug() << " 日期:" << logMatch.captured(1);
qDebug() << " 时间:" << logMatch.captured(2);
qDebug() << " 级别:" << logMatch.captured(3);
qDebug() << " 消息:" << logMatch.captured(4);
}
}
3.2 查找并替换
void findAndReplace()
{
QString str = "The quick brown fox jumps over the lazy dog.";
// 6.1 replace() - 简单替换
QString replaced1 = str;
replaced1.replace("fox", "cat");
qDebug() << "替换 'fox' 为 'cat':" << replaced1;
// 6.2 替换所有出现
QString str2 = "apple apple orange apple";
QString replaced2 = str2;
replaced2.replace("apple", "pear");
qDebug() << "替换所有 'apple' 为 'pear':" << replaced2;
// 6.3 使用正则表达式替换
QString html = "<p>Hello <b>World</b>!</p>";
QRegularExpression tagRegex(R"(<[^>]*>)");
QString textOnly = html;
textOnly.replace(tagRegex, "");
qDebug() << "移除HTML标签:" << textOnly;
// 6.4 使用lambda进行复杂替换
QString numbers = "1, 2, 3, 4, 5";
QRegularExpression numRegex(R"(\d+)");
QString doubled = numbers;
doubled.replace(numRegex, const QRegularExpressionMatch &match {
int num = match.captured(0).toInt();
return QString::number(num * 2);
});
qDebug() << "数字加倍:" << doubled;
}
4. 完整的查找工具类
4.1 StringFinder 类
// StringFinder.h
#ifndef STRINGFINDER_H
#define STRINGFINDER_H
#include <QString>
#include <QVector>
#include <QRegularExpression>
#include <QPair>
class StringFinder
{
public:
// 查找单个子串的所有出现
static QVector<int> findAll(const QString& text,
const QString& substring,
Qt::CaseSensitivity cs = Qt::CaseSensitive);
// 查找多个子串的所有出现
static QVector<QPair<QString, int>> findAllMultiple(const QString& text,
const QStringList& substrings,
Qt::CaseSensitivity cs = Qt::CaseSensitive);
// 使用正则表达式查找
static QVector<QRegularExpressionMatch> findAllRegex(const QString& text,
const QRegularExpression& regex);
// 统计子串出现次数
static int countOccurrences(const QString& text,
const QString& substring,
Qt::CaseSensitivity cs = Qt::CaseSensitive);
// 查找最长的公共子串
static QString findLongestCommonSubstring(const QString& str1,
const QString& str2);
// 查找最长的重复子串
static QString findLongestRepeatedSubstring(const QString& text);
// 查找所有单词及其位置
static QVector<QPair<QString, int>> findAllWords(const QString& text);
// 模糊查找(支持通配符)
static QVector<int> fuzzyFind(const QString& text,
const QString& pattern,
Qt::CaseSensitivity cs = Qt::CaseSensitive);
// 查找并高亮显示
static QString highlightAll(const QString& text,
const QString& substring,
const QString& startTag = "<mark>",
const QString& endTag = "</mark>",
Qt::CaseSensitivity cs = Qt::CaseSensitive);
private:
// 计算编辑距离(用于模糊匹配)
static int editDistance(const QString& s1, const QString& s2);
// 构建后缀数组
static QVector<int> buildSuffixArray(const QString& text);
};
#endif // STRINGFINDER_H
// StringFinder.cpp
#include "StringFinder.h"
#include <QDebug>
#include <algorithm>
QVector<int> StringFinder::findAll(const QString& text,
const QString& substring,
Qt::CaseSensitivity cs)
{
QVector<int> 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<QPair<QString, int>> StringFinder::findAllMultiple(const QString& text,
const QStringList& substrings,
Qt::CaseSensitivity cs)
{
QVector<QPair<QString, int>> results;
for (const QString& sub : substrings) {
QVector<int> positions = findAll(text, sub, cs);
for (int pos : positions) {
results.append(qMakePair(sub, pos));
}
}
// 按位置排序
std::sort(results.begin(), results.end(),
const QPair<QString, int>& a, const QPair<QString, int>& b {
return a.second < b.second;
});
return results;
}
QVector<QRegularExpressionMatch> StringFinder::findAllRegex(const QString& text,
const QRegularExpression& regex)
{
QVector<QRegularExpressionMatch> matches;
if (!regex.isValid()) {
qWarning() << "无效的正则表达式:" << regex.errorString();
return matches;
}
QRegularExpressionMatchIterator iterator = regex.globalMatch(text);
while (iterator.hasNext()) {
matches.append(iterator.next());
}
return matches;
}
int StringFinder::countOccurrences(const QString& text,
const QString& 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& str1,
const QString& str2)
{
int m = str1.length();
int n = str2.length();
if (m == 0 || n == 0) {
return QString();
}
// 创建DP表
QVector<QVector<int>> dp(m + 1, QVector<int>(n + 1, 0));
int maxLength = 0;
int endPos = 0;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (str1[i-1] == str2[j-1]) {
dp[i][j] = dp[i-1][j-1] + 1;
if (dp[i][j] > maxLength) {
maxLength = dp[i][j];
endPos = i;
}
}
}
}
if (maxLength == 0) {
return QString();
}
return str1.mid(endPos - maxLength, maxLength);
}
QString StringFinder::findLongestRepeatedSubstring(const QString& text)
{
int n = text.length();
if (n < 2) {
return QString();
}
// 构建后缀数组
QVector<int> suffixArray = buildSuffixArray(text);
// 查找最长公共前缀
QString longest = "";
for (int i = 0; i < n - 1; i++) {
int idx1 = suffixArray[i];
int idx2 = suffixArray[i + 1];
// 查找公共前缀
int k = 0;
while (idx1 + k < n && idx2 + k < n &&
text[idx1 + k] == text[idx2 + k]) {
k++;
}
if (k > longest.length()) {
longest = text.mid(idx1, k);
}
}
return longest;
}
QVector<QPair<QString, int>> StringFinder::findAllWords(const QString& text)
{
QVector<QPair<QString, int>> 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<int> StringFinder::fuzzyFind(const QString& text,
const QString& pattern,
Qt::CaseSensitivity cs)
{
QVector<int> 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 <= text.length() - pattern.length(); i++) {
bool found = true;
int patternIndex = 0;
for (int j = i; j < text.length() && patternIndex < pattern.length(); j++) {
if (textLower[j] == patternLower[patternIndex]) {
patternIndex++;
}
}
if (patternIndex == pattern.length()) {
positions.append(i);
}
}
return positions;
}
QString StringFinder::highlightAll(const QString& text,
const QString& substring,
const QString& startTag,
const QString& endTag,
Qt::CaseSensitivity cs)
{
if (substring.isEmpty()) {
return text;
}
QString result = text;
QVector<int> positions = findAll(text, substring, cs);
// 从后往前插入标签,避免位置偏移
for (int i = positions.size() - 1; i >= 0; i--) {
int pos = positions[i];
result.insert(pos + substring.length(), endTag);
result.insert(pos, startTag);
}
return result;
}
int StringFinder::editDistance(const QString& s1, const QString& s2)
{
int m = s1.length();
int n = s2.length();
QVector<QVector<int>> dp(m + 1, QVector<int>(n + 1));
for (int i = 0; i <= m; i++) {
dp[i][0] = i;
}
for (int j = 0; j <= n; j++) {
dp[0][j] = j;
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (s1[i-1] == s2[j-1]) {
dp[i][j] = dp[i-1][j-1];
} else {
dp[i][j] = 1 + qMin(qMin(dp[i-1][j], dp[i][j-1]), dp[i-1][j-1]);
}
}
}
return dp[m][n];
}
QVector<int> StringFinder::buildSuffixArray(const QString& text)
{
int n = text.length();
QVector<int> suffixArray(n);
// 初始化后缀数组
for (int i = 0; i < n; i++) {
suffixArray[i] = i;
}
// 简单排序(对于大文本,应使用更高效的算法)
std::sort(suffixArray.begin(), suffixArray.end(),
int a, int b {
return text.mid(a) < text.mid(b);
});
return suffixArray;
}
5. 实际应用示例
5.1 日志分析工具
#include "StringFinder.h"
#include <QFile>
#include <QTextStream>
#include <QDateTime>
class LogAnalyzer
{
public:
struct LogEntry {
QDateTime timestamp;
QString level;
QString message;
int lineNumber;
};
QVector<LogEntry> parseLogFile(const QString& filePath)
{
QVector<LogEntry> entries;
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qWarning() << "无法打开日志文件:" << filePath;
return entries;
}
QTextStream in(&file);
int lineNumber = 0;
// 日志格式: [2023-12-20 14:30:25] [INFO] 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<LogEntry> searchInLogs(const QVector<LogEntry>& entries,
const QString& searchTerm,
Qt::CaseSensitivity cs = Qt::CaseInsensitive)
{
QVector<LogEntry> results;
for (const LogEntry& entry : entries) {
if (entry.message.contains(searchTerm, cs) ||
entry.level.contains(searchTerm, cs)) {
results.append(entry);
}
}
return results;
}
QVector<LogEntry> searchByRegex(const QVector<LogEntry>& entries,
const QRegularExpression& regex)
{
QVector<LogEntry> results;
for (const LogEntry& entry : entries) {
if (regex.match(entry.message).hasMatch() ||
regex.match(entry.level).hasMatch()) {
results.append(entry);
}
}
return results;
}
QMap<QString, int> countByLevel(const QVector<LogEntry>& entries)
{
QMap<QString, int> counts;
for (const LogEntry& entry : entries) {
counts[entry.level]++;
}
return counts;
}
};
5.2 文本搜索工具
class TextSearchTool
{
public:
struct SearchResult {
int lineNumber;
int position;
QString line;
QString matchedText;
};
QVector<SearchResult> searchInFile(const QString& filePath,
const QString& searchTerm,
Qt::CaseSensitivity cs = Qt::CaseSensitive)
{
QVector<SearchResult> results;
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
return results;
}
QTextStream in(&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<SearchResult> searchWithRegex(const QString& filePath,
const QRegularExpression& regex)
{
QVector<SearchResult> results;
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
return results;
}
QTextStream in(&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& text,
const QVector<SearchResult>& results,
const QString& startTag = "<span style='background-color: yellow;'>",
const QString& endTag = "</span>")
{
QString highlighted = text;
// 从后往前插入标签,避免位置偏移
for (int i = results.size() - 1; i >= 0; i--) {
const SearchResult& result = results[i];
highlighted.insert(result.position + result.matchedText.length(), endTag);
highlighted.insert(result.position, startTag);
}
return highlighted;
}
};
6. 性能优化
6.1 高效查找算法
#include <QHash>
#include <QSet>
class EfficientStringSearcher
{
public:
// Boyer-Moore算法实现
static QVector<int> boyerMooreSearch(const QString& text,
const QString& pattern,
Qt::CaseSensitivity cs = Qt::CaseSensitive)
{
QVector<int> positions;
int n = text.length();
int m = pattern.length();
if (m == 0 || n == 0 || m > n) {
return positions;
}
// 预处理坏字符表
QHash<QChar, int> badChar;
for (int i = 0; i < m - 1; i++) {
badChar[pattern[i]] = m - 1 - i;
}
// 搜索
int s = 0;
while (s <= n - m) {
int j = m - 1;
// 从右向左比较
while (j >= 0) {
QChar textChar = (cs == Qt::CaseInsensitive) ?
text[s + j].toLower() : text[s + j];
QChar patternChar = (cs == Qt::CaseInsensitive) ?
pattern[j].toLower() : pattern[j];
if (textChar != patternChar) {
break;
}
j--;
}
if (j < 0) {
// 找到匹配
positions.append(s);
s += (s + m < n) ? badChar.value(text[s + m], m) : 1;
} else {
// 根据坏字符规则移动
QChar badCharValue = (cs == Qt::CaseInsensitive) ?
text[s + j].toLower() : text[s + j];
int shift = badChar.value(badCharValue, m);
s += qMax(1, shift - (m - 1 - j));
}
}
return positions;
}
// KMP算法实现
static QVector<int> kmpSearch(const QString& text,
const QString& pattern,
Qt::CaseSensitivity cs = Qt::CaseSensitive)
{
QVector<int> positions;
int n = text.length();
int m = pattern.length();
if (m == 0 || n == 0 || m > n) {
return positions;
}
// 构建部分匹配表
QVector<int> lps(m, 0);
int len = 0;
int i = 1;
while (i < m) {
QChar c1 = (cs == Qt::CaseInsensitive) ? pattern[i].toLower() : pattern[i];
QChar c2 = (cs == Qt::CaseInsensitive) ? pattern[len].toLower() : pattern[len];
if (c1 == c2) {
len++;
lps[i] = len;
i++;
} else {
if (len != 0) {
len = lps[len - 1];
} else {
lps[i] = 0;
i++;
}
}
}
// 搜索
i = 0; // text的索引
int j = 0; // pattern的索引
while (i < n) {
QChar textChar = (cs == Qt::CaseInsensitive) ? text[i].toLower() : text[i];
QChar patternChar = (cs == Qt::CaseInsensitive) ? pattern[j].toLower() : pattern[j];
if (textChar == patternChar) {
i++;
j++;
}
if (j == m) {
// 找到匹配
positions.append(i - j);
j = lps[j - 1];
} else if (i < n && textChar != patternChar) {
if (j != 0) {
j = lps[j - 1];
} else {
i++;
}
}
}
return positions;
}
// 多模式搜索(Aho-Corasick算法)
class AhoCorasick
{
public:
struct Node {
QHash<QChar, int> next;
int fail = 0;
QVector<int> output;
};
AhoCorasick() {
nodes.append(Node()); // 根节点
}
void addPattern(const QString& pattern, int patternId) {
int current = 0;
for (QChar ch : pattern) {
if (!nodes[current].next.contains(ch)) {
nodes[current].next[ch] = nodes.size();
nodes.append(Node());
}
current = nodes[current].next[ch];
}
nodes[current].output.append(patternId);
}
void buildFailureLinks() {
QQueue<int> queue;
// 第一层的失败链接指向根节点
for (auto it = nodes[0].next.begin(); it != nodes[0].next.end(); ++it) {
int nextNode = it.value();
nodes[nextNode].fail = 0;
queue.enqueue(nextNode);
}
while (!queue.isEmpty()) {
int current = queue.dequeue();
for (auto it = nodes[current].next.begin(); it != nodes[current].next.end(); ++it) {
QChar ch = it.key();
int child = it.value();
int fail = nodes[current].fail;
while (fail != 0 && !nodes[fail].next.contains(ch)) {
fail = nodes[fail].fail;
}
if (nodes[fail].next.contains(ch)) {
nodes[child].fail = nodes[fail].next[ch];
} else {
nodes[child].fail = 0;
}
// 合并输出
nodes[child].output.append(nodes[nodes[child].fail].output);
queue.enqueue(child);
}
}
}
QHash<int, QVector<int>> search(const QString& text) {
QHash<int, QVector<int>> results;
int current = 0;
for (int i = 0; i < text.length(); i++) {
QChar ch = text[i];
while (current != 0 && !nodes[current].next.contains(ch)) {
current = nodes[current].fail;
}
if (nodes[current].next.contains(ch)) {
current = nodes[current].next[ch];
} else {
current = 0;
}
for (int patternId : nodes[current].output) {
results[patternId].append(i);
}
}
return results;
}
private:
QVector<Node> nodes;
};
};
7. 完整的示例程序
// main.cpp
#include <QCoreApplication>
#include <QDebug>
#include "StringFinder.h"
#include "EfficientStringSearcher.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug() << "=== QString 查找子串示例 ===";
// 示例1: 基本查找
{
qDebug() << "\n1. 基本查找示例:";
QString text = "The quick brown fox jumps over the lazy dog.";
qDebug() << "文本:" << text;
qDebug() << "包含 'fox':" << text.contains("fox");
qDebug() << "'fox' 位置:" << text.indexOf("fox");
qDebug() << "'the' 最后位置:" << text.lastIndexOf("the");
}
// 示例2: 使用StringFinder
{
qDebug() << "\n2. 使用StringFinder:";
QString text = "apple banana apple orange apple";
QVector<int> positions = StringFinder::findAll(text, "apple");
qDebug() << "'apple' 所有位置:" << positions;
int count = StringFinder::countOccurrences(text, "apple");
qDebug() << "'apple' 出现次数:" << count;
QString highlighted = StringFinder::highlightAll(text, "apple", "[", "]");
qDebug() << "高亮显示:" << highlighted;
}
// 示例3: 正则表达式查找
{
qDebug() << "\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() << "找到邮箱:" << match.captured(0);
}
QRegularExpression phoneRegex(R"(\d{3}-\d{3}-\d{4})");
match = phoneRegex.match(text);
if (match.hasMatch()) {
qDebug() << "找到电话:" << match.captured(0);
}
}
// 示例4: 高效算法比较
{
qDebug() << "\n4. 高效算法比较:";
QString text = QString(10000, 'a') + "b" + QString(10000, 'a');
QString pattern = "aaaab";
// 普通查找
auto start = std::chrono::high_resolution_clock::now();
QVector<int> naivePositions = StringFinder::findAll(text, pattern);
auto end = std::chrono::high_resolution_clock::now();
auto naiveTime = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
// KMP算法
start = std::chrono::high_resolution_clock::now();
QVector<int> kmpPositions = EfficientStringSearcher::kmpSearch(text, pattern);
end = std::chrono::high_resolution_clock::now();
auto kmpTime = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
// Boyer-Moore算法
start = std::chrono::high_resolution_clock::now();
QVector<int> bmPositions = EfficientStringSearcher::boyerMooreSearch(text, pattern);
end = std::chrono::high_resolution_clock::now();
auto bmTime = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
qDebug() << "朴素算法时间:" << naiveTime << "微秒";
qDebug() << "KMP算法时间:" << kmpTime << "微秒";
qDebug() << "Boyer-Moore算法时间:" << bmTime << "微秒";
qDebug() << "找到的位置数量:" << naivePositions.size();
}
// 示例5: 多模式搜索
{
qDebug() << "\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() << "在 '" << text << "' 中找到的模式:";
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() << " 模式 '" << pattern << "' 在位置:" << it.value();
}
}
return 0;
}
8. 重要注意事项
-
性能考虑:
- 对于小文本,使用简单的
indexOf()足够 - 对于大文本或频繁搜索,考虑使用高效算法
- 避免在循环中重复编译正则表达式
- 对于小文本,使用简单的
-
编码问题:
- 确保文本编码正确
- 处理多字节字符
- 注意大小写敏感设置
-
内存管理:
- 避免创建不必要的临时字符串
- 使用引用传递大字符串
- 及时释放不需要的内存
-
错误处理:
- 检查查找结果(-1表示未找到)
- 验证正则表达式的有效性
- 处理空字符串和边界情况
-
国际化:
- 考虑不同语言的文本处理
- 处理Unicode字符
- 注意区域设置
通过上述方法,您可以在Qt中高效地查找和处理子串。根据具体需求选择合适的查找方法和算法。
上一篇:QT设计师里的Text Edit、Plain Text Edit、Text Browser分别用什么作用,又有什么区别

不积跬步,无以至千里。
代码铸就星河,探索永无止境
在这片由逻辑与算法编织的星辰大海中,每一次报错都是宇宙抛来的谜题,每一次调试都是与未知的深度对话。不要因短暂的“运行失败”而止步,因为真正的光芒,往往诞生于反复试错的暗夜。
请铭记:
- 你写下的每一行代码,都在为思维锻造韧性;
- 你破解的每一个Bug,都在为认知推开新的门扉;
- 你坚持的每一分钟,都在为未来的飞跃积蓄势能。
技术的疆域没有终点,只有不断刷新的起点。无论是递归般的层层挑战,还是如异步并发的复杂困局,你终将以耐心为栈、以好奇心为指针,遍历所有可能。
向前吧,开发者!
让代码成为你攀登的绳索,让逻辑化作照亮迷雾的灯塔。当你在终端看到“Success”的瞬间,便是宇宙对你坚定信念的回响——
此刻的成就,永远只是下一个奇迹的序章! 🚀
(将技术挑战比作宇宙探索,用代码、算法等意象强化身份认同,传递“持续突破”的信念,结尾以动态符号激发行动力。)
//c++ hello world示例
#include <iostream> // 引入输入输出流库
int main() {
std::cout << "Hello World!" << std::endl; // 输出字符串并换行
return 0; // 程序正常退出
}
print("Hello World!") # 调用内置函数输出字符串
package main // 声明主包
#python hello world示例
import "fmt" // 导入格式化I/O库
//go hello world示例
func main() {
fmt.Println("Hello World!") // 输出并换行
}
//c# hello world示例
using System; // 引入System命名空间
class Program {
static void Main() {
Console.WriteLine("Hello World!"); // 输出并换行
Console.ReadKey(); // 等待按键(防止控制台闪退)
}
}
更多推荐

所有评论(0)