🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# Qt5 中的字符串 > 原文: [http://zetcode.com/gui/qt5/strings/](http://zetcode.com/gui/qt5/strings/) 在本章中,我们将使用字符串。 Qt5 具有用于处理字符串的`QString`类。 它非常强大,并且具有多种方法。 `QString`类提供 Unicode 字符串。 它将字符串存储为 16 位`QChars`。 每个`QChar`对应一个 Unicode 4.0 字符。 与许多其他编程语言中的字符串不同,可以修改`QString`。 在本章的示例中,我们将不需要 Qt GUI 模块。 我们将创建命令行程序。 由于默认情况下包括 Qt GUI,因此我们可以通过在项目文件中添加`QT -= gui`声明来禁用它。 ## 第一个例子 在第一个示例中,我们将使用`QString`类的一些基本方法。 `basic.cpp` ```cpp #include <QTextStream> int main(void) { QTextStream out(stdout); QString a = "love"; a.append(" chess"); a.prepend("I "); out << a << endl; out << "The a string has " << a.count() << " characters" << endl; out << a.toUpper() << endl; out << a.toLower() << endl; return 0; } ``` 在代码示例中,我们启动`QString`。 我们附加并添加一些其他文字。 我们打印字符串的长度。 最后,我们以大写和小写形式显示修改后的字符串。 ```cpp QString a = "love"; ``` 启动`QString`。 ```cpp a.append(" chess"); a.prepend("I "); ``` 我们将文本附加和添加到初始字符串之前。 该字符串就地修改。 ```cpp out << a << endl; ``` 终端上印有`I love chess`。 ```cpp out << "The a string has " << a.count() << " characters" << endl; ``` `count()`方法返回字符串中的字符数。 `length()`和`size()`方法是等效的。 ```cpp out << a.toUpper() << endl; out << a.toLower() << endl; ``` 这两个方法返回字符串的大写和小写副本。 他们不修改字符串,而是返回新的修改后的字符串副本。 输出: ```cpp $ ./basic I love chess The a string has 12 characters I LOVE CHESS i love chess ``` ## 初始化字符串 `QString`可以通过多种方式初始化。 `init.cpp` ```cpp #include <QTextStream> int main(void) { QTextStream out(stdout); QString str1 = "The night train"; out << str1 << endl; QString str2("A yellow rose"); out << str2 << endl; std::string s1 = "A blue sky"; QString str3 = s1.c_str(); out << str3 << endl; std::string s2 = "A thick fog"; QString str4 = QString::fromLatin1(s2.data(), s2.size()); out << str4 << endl; char s3[] = "A deep forest"; QString str5(s3); out << str5 << endl; return 0; } ``` 我们介绍了五种初始化`QString`的方法。 ```cpp QString str1 = "The night train"; ``` 这是在计算机语言中初始化字符串的传统方式。 ```cpp QString str2("A yellow rose"); ``` 这是启动`QString`的对象方式。 ```cpp std::string s1 = "A blue sky"; QString str3 = s1.c_str(); ``` 我们有一个来自 C++ 标准库的字符串对象。 我们使用其`c_str()`方法来生成以空字符结尾的字符序列。 该字符数组(字符串的经典 C 表示形式)可以分配给`QString`变量。 ```cpp std::string s2 = "A thick fog"; QString str4 = QString::fromLatin1(s2.data(), s2.size()); ``` 在这些代码行中,我们将标准 C++ 字符串转换为`QString`。 我们利用`fromLatin1()`方法。 它需要一个指向字符数组的指针。 指针通过`std::string`的`data()`方法返回。 第二个参数是`std::string`的大小。 ```cpp char s3[] = "A deep forest"; QString str5(s3); ``` 这是一个 C 字符串; 它是一个字符数组。 `QString`构造器之一可以将`char`数组作为参数。 输出: ```cpp $ ./init The night train A yellow rose A blue sky A thick fog A deep forest ``` ## 访问字符串元素 `QString`是`QChars`的序列。 可以使用`[]`运算符或`at()`方法访问字符串的元素。 `access.cpp` ```cpp #include <QTextStream> int main(void) { QTextStream out(stdout); QString a = "Eagle"; out << a[0] << endl; out << a[4] << endl; out << a.at(0) << endl; if (a.at(5).isNull()) { out << "Outside the range of the string" << endl; } return 0; } ``` 我们从特定的`QString`打印一些单独的字符。 ```cpp out << a[0] << endl; out << a[4] << endl; ``` 我们打印字符串的第一个和第五个元素。 ```cpp out << a.at(0) << endl; ``` 使用`at()`方法,我们检索字符串的第一个字符。 ```cpp if (a.at(5).isNull()) { out << "Outside the range of the string" << endl; } ``` 如果我们尝试访问字符串字符范围之外的字符,则`at()`方法返回`null`。 输出: ```cpp $ ./access E e E Outside the range of the string ``` ## 字符串长度 有三种获取字符串长度的方法。 `size()`,`count()`和`length()`方法。 所有人都做同样的事情。 它们返回指定字符串中的字符数。 `length.cpp` ```cpp #include <QTextStream> int main(void) { QTextStream out(stdout); QString s1 = "Eagle"; QString s2 = "Eagle\n"; QString s3 = "Eagle "; QString s4 = "орел"; out << s1.length() << endl; out << s2.length() << endl; out << s3.length() << endl; out << s4.length() << endl; return 0; } ``` 我们得到四个字符串的大小。 ```cpp QString s2 = "Eagle\n"; QString s3 = "Eagle "; ``` 这两个字符串中的每个字符串都有一个白色字符。 ```cpp QString s4 = "орел"; ``` 此字符串由俄语字母组成。 输出: ```cpp $ ./length 5 6 6 4 ``` 从输出中我们可以看到`length()`方法也计算了白色字符。 ## 字符串构建 动态字符串构建使我们可以用实际值替换特定的控制字符。 我们使用`arg()`方法进行插值。 `building.cpp` ```cpp #include <QTextStream> int main() { QTextStream out(stdout); QString s1 = "There are %1 white roses"; int n = 12; out << s1.arg(n) << endl; QString s2 = "The tree is %1 m high"; double h = 5.65; out << s2.arg(h) << endl; QString s3 = "We have %1 lemons and %2 oranges"; int ln = 12; int on = 4; out << s3.arg(ln).arg(on) << endl; return 0; } ``` 将要替换的标记以`%`字符开头。 下一个字符是指定自变量的数字。 一个字符串可以有多个参数。 `arg()`方法已重载,它可以接受整数,长数字,字符和`QChar`等。 ```cpp QString s1 = "There are %1 white roses"; int n = 12; ``` `%1`是我们计划替换的标记。 我们定义了一个整数。 ```cpp out << s1.arg(n) << endl; ``` `arg()`方法采用整数。 `%1`标记被`n`变量的值替换。 ```cpp QString s2 = "The tree is %1 m high"; double h = 5.65; out << s2.arg(h) << endl; ``` 这三行对于一个双数执行相同的操作。 正确的`arg()`方法将被自动调用。 ```cpp QString s3 = "We have %1 lemons and %2 oranges"; int ln = 12; int on = 4; out << s3.arg(ln).arg(on) << endl; ``` 我们可以有多个控制字符。 `%1`引用第一个参数,`%2`引用第二个参数。 `arg()`方法在连续的链中调用。 输出: ```cpp $ ./building There are 12 white roses The tree is 5.65 m high We have 12 lemons and 4 oranges ``` ## 子串 在进行文本处理时,我们需要找到普通字符串的子字符串。 我们有`left()`,`mid()`和`right()`方法可供我们使用。 `substrings.cpp` ```cpp #include <QTextStream> int main(void) { QTextStream out(stdout); QString str = "The night train"; out << str.right(5) << endl; out << str.left(9) << endl; out << str.mid(4, 5) << endl; QString str2("The big apple"); QStringRef sub(&str2, 0, 7); out << sub.toString() << endl; return 0; } ``` 我们将使用这三种方法查找给定字符串的一些子字符串。 ```cpp out << str.right(5) << endl; ``` 通过`right()`方法,我们获得`str`字符串的最右边五个字符。 将打印`train`。 ```cpp out << str.left(9) << endl; ``` 使用`left()`方法,我们获得`str`字符串的最左边九个字符。 将打印`night`。 ```cpp out << str.mid(4, 5) << endl; ``` 使用`mid()`方法,我们从第 4 个位置开始得到 5 个字符。 打印`night`。 ```cpp QString str2("The big apple"); QStringRef sub(&str2, 0, 7); ``` `QStringRef`类是`QString`的只读版本。 在这里,我们创建`str2`字符串一部分的`QStringRef`。 第二个参数是位置,第三个参数是子字符串的长度。 输出: ```cpp $ ./substrings train The night night The big ``` ## 遍历字符串 `QString`由`QChars`组成。 我们可以遍历`QString`以访问字符串的每个元素。 `looping.cpp` ```cpp #include <QTextStream> int main(void) { QTextStream out(stdout); QString str = "There are many stars."; foreach (QChar qc, str) { out << qc << " "; } out << endl; for (QChar *it=str.begin(); it!=str.end(); ++it) { out << *it << " " ; } out << endl; for (int i = 0; i < str.size(); ++i) { out << str.at(i) << " "; } out << endl; return 0; } ``` 我们展示了通过`QString`的三种方法。 在将字母打印到终端时,我们在字母之间添加空格字符。 ```cpp foreach (QChar qc, str) { out << qc << " "; } ``` `foreach`关键字是 C++ 语言的 Qt 扩展。 关键字的第一个参数是字符串元素,第二个参数是字符串。 ```cpp for (QChar *it=str.begin(); it!=str.end(); ++it) { out << *it << " " ; } ``` 在此代码中,我们使用迭代器遍历字符串。 ```cpp for (int i = 0; i < str.size(); ++i) { out << str.at(i) << " "; } ``` 我们计算字符串的大小,并使用`at()`方法访问字符串元素。 输出: ```cpp $ ./looping T h e r e a r e m a n y s t a r s . T h e r e a r e m a n y s t a r s . T h e r e a r e m a n y s t a r s . ``` ## 字符串比较 `QString::compare()`静态方法用于比较两个字符串。 该方法返回一个整数。 如果返回的值小于零,则第一个字符串小于第二个字符串。 如果返回零,则两个字符串相等。 最后,如果返回的值大于零,则第一个字符串大于第二个字符串。 “较少”是指字符串的特定字符在字符表中位于另一个字符之前。 比较字符串的方法如下:比较两个字符串的第一个字符; 如果它们相等,则比较以下两个字符,直到找到一些不同的字符或发现所有字符都匹配为止。 `comparing.cpp` ```cpp #include <QTextStream> #define STR_EQUAL 0 int main(void) { QTextStream out(stdout); QString a = "Rain"; QString b = "rain"; QString c = "rain\n"; if (QString::compare(a, b) == STR_EQUAL) { out << "a, b are equal" << endl; } else { out << "a, b are not equal" << endl; } out << "In case insensitive comparison:" << endl; if (QString::compare(a, b, Qt::CaseInsensitive) == STR_EQUAL) { out << "a, b are equal" << endl; } else { out << "a, b are not equal" << endl; } if (QString::compare(b, c) == STR_EQUAL) { out << "b, c are equal" << endl; } else { out << "b, c are not equal" << endl; } c.chop(1); out << "After removing the new line character" << endl; if (QString::compare(b, c) == STR_EQUAL) { out << "b, c are equal" << endl; } else { out << "b, c are not equal" << endl; } return 0; } ``` 我们将使用`compare()`方法进行区分大小写和不区分大小写的比较。 ```cpp #define STR_EQUAL 0 ``` 为了更好的代码清晰度,我们定义`STR_EQUAL`常量。 ```cpp QString a = "Rain"; QString b = "rain"; QString c = "rain\n"; ``` 我们将比较这三个字符串。 ```cpp if (QString::compare(a, b) == STR_EQUAL) { out << "a, b are equal" << endl; } else { out << "a, b are not equal" << endl; } ``` 我们比较`a`和`b`字符串,它们不相等。 它们的第一个字符不同。 ```cpp if (QString::compare(a, b, Qt::CaseInsensitive) == STR_EQUAL) { out << "a, b are equal" << endl; } else { out << "a, b are not equal" << endl; } ``` 如果不区分大小写,则字符串相等。 `Qt::CaseInsensitive`使比较大小写不敏感。 ```cpp c.chop(1); ``` `chop()`方法从`c`字符串中删除最后一个字符。 现在`b`和`c`字符串相等。 输出: ```cpp $ ./comparing a, b are not equal In case insensitive comparison: a, b are equal b, c are not equal After removing the new line character b, c are equal ``` ## 转换字符串 字符串通常需要转换为其他数据类型,反之亦然。 `toInt()`,`toFloat()`和`toLong()`是将字符串转换为整数,浮点数和长整数的三种`QString`方法。 (还有更多这样的方法。)`setNum()`方法将各种数字数据类型转换为字符串。 该方法已重载,并且自动调用了正确的方法。 `Output` ```cpp #include <QTextStream> int main(void) { QTextStream out(stdout); QString s1 = "12"; QString s2 = "15"; QString s3, s4; out << s1.toInt() + s2.toInt() << endl; int n1 = 30; int n2 = 40; out << s3.setNum(n1) + s4.setNum(n2) << endl; return 0; } ``` 在示例中,我们将两个字符串转换为整数并将其相加。 然后,我们将两个整数转换为字符串并将其连接起来。 ```cpp out << s1.toInt() + s2.toInt() << endl; ``` `toInt()`方法将字符串转换为整数。 我们添加两个转换为字符串的数字。 ```cpp out << s3.setNum(n1) + s4.setNum(n2) << endl; ``` 在这种情况下,`setNum()`方法将整数转换为字符串。 我们连接两个字符串。 输出: ```cpp $ ./converts 27 3040 ``` ## 字符 字符分为各种类别:数字,字母,空格和标点符号。 每个`QString`都由`QChar`组成。 `QChar`具有`isDigit()`,`isLetter()`,`isSpace()`和`isPunct()`方法来执行作业。 `letters.cpp` ```cpp #include <QTextStream> int main(void) { QTextStream out(stdout); int digits = 0; int letters = 0; int spaces = 0; int puncts = 0; QString str = "7 white, 3 red roses."; foreach(QChar s, str) { if (s.isDigit()) { digits++; } else if (s.isLetter()) { letters++; } else if (s.isSpace()) { spaces++; } else if (s.isPunct()) { puncts++; } } out << QString("There are %1 characters").arg(str.count()) << endl; out << QString("There are %1 letters").arg(letters) << endl; out << QString("There are %1 digits").arg(digits) << endl; out << QString("There are %1 spaces").arg(spaces) << endl; out << QString("There are %1 punctuation characters").arg(puncts) << endl; return 0; } ``` 在示例中,我们定义了一个简单的句子。 我们将计算句子中的数字,字母,空格和标点符号的数量。 ```cpp int digits = 0; int letters = 0; int spaces = 0; int puncts = 0; ``` 我们为每个字符类别定义一个整数变量。 ```cpp QString str = "7 white, 3 red roses."; ``` 这是要检查的句子。 ```cpp foreach(QChar s, str) { if (s.isDigit()) { digits++; } else if (s.isLetter()) { letters++; } else if (s.isSpace()) { spaces++; } else if (s.isPunct()) { puncts++; } } ``` 我们使用`foreach`关键字来浏览`QString`。 每个元素都是`QChar`。 我们使用`QChar`类的方法来确定字符的类别。 ```cpp out << QString("There are %1 characters").arg(str.count()) << endl; out << QString("There are %1 letters").arg(letters) << endl; out << QString("There are %1 digits").arg(digits) << endl; out << QString("There are %1 spaces").arg(spaces) << endl; out << QString("There are %1 punctuation characters").arg(puncts) << endl; ``` 使用字符串插值,我们将数字打印到终端。 输出: ```cpp $ ./letters There are 21 characters There are 13 letters There are 2 digits There are 4 spaces There are 2 punctuation characters ``` ## 修改字符串 某些方法(例如`toLower()`方法)返回原始字符串的新修改副本。 其他方法可就地修改字符串。 我们将介绍其中的一些。 `modify.cpp` ```cpp #include <QTextStream> int main(void) { QTextStream out(stdout); QString str = "Lovely"; str.append(" season"); out << str << endl; str.remove(10, 3); out << str << endl; str.replace(7, 3, "girl"); out << str << endl; str.clear(); if (str.isEmpty()) { out << "The string is empty" << endl; } return 0; } ``` 我们描述了四种就地修改字符串的方法。 ```cpp str.append(" season"); ``` `append()`方法在字符串的末尾添加一个新字符串。 ```cpp str.remove(10, 3); ``` `remove()`方法从位置 10 开始从字符串中删除 3 个字符。 ```cpp str.replace(7, 3, "girl"); ``` `replace()`方法用指定的字符串替换从`7`位置开始的`3`字符。 ```cpp str.clear(); ``` `clear()`方法清除字符串。 输出: ```cpp $ ./modify Lovely season Lovely sea Lovely girl The string is empty ``` 在本章中,我们使用了 Qt5 中的字符串。 ## 对齐字符串 拥有整洁的输出是常见的要求。 我们可以使用`leftJustified()`和`rightJustified()`方法来对齐字符串。 `right_align.cpp` ```cpp #include <QTextStream> int main(void) { QTextStream out(stdout); QString field1 = "Name: "; QString field2 = "Occupation: "; QString field3 = "Residence: "; QString field4 = "Marital status: "; int width = field4.size(); out << field1.rightJustified(width, ' ') << "Robert\n"; out << field2.rightJustified(width, ' ') << "programmer\n"; out << field3.rightJustified(width, ' ') << "New York\n"; out << field4.rightJustified(width, ' ') << "single\n"; return 0; } ``` 该示例将字段字符串向右对齐。 ```cpp int width = field4.size(); ``` 我们计算最宽字符串的大小。 ```cpp out << field1.rightJustified(width, ' ') << "Robert\n"; ``` `rightJustified()`方法返回具有`width`字符的字符串。 如果字符串较短,则其余部分将使用提供的字符填充。 在我们的情况下,它是一个空格字符。 输出: ```cpp $ ./right_align Name: Robert Occupation: programmer Residence: New York Marital status: single ``` ## 转义字符 Qt5 具有`toHtmlEscaped()`方法,该方法将纯文本字符串转换为将 HTML 元字符`<`,`>`,`&`和`"`替换为 HTML 命名实体的 HTML 字符串。 ```cpp $ cat cprog.c #include <stdio.h> int main(void) { for (int i=1; i<=10; i++) { printf("Bottle %d\n", i); } } ``` 此 C 包含 HTML 元字符。 `html_escape.cpp` ```cpp #include <QTextStream> #include <QFile> int main(void) { QTextStream out(stdout); QFile file("cprog.c"); if (!file.open(QIODevice::ReadOnly)) { qWarning("Cannot open file for reading"); return 1; } QTextStream in(&file); QString allText = in.readAll(); out << allText.toHtmlEscaped() << endl; file.close(); return 0; } ``` 该示例读取一个 C 程序,并将元字符替换为其命名的实体。 输出: ```cpp $ ./html_escape #include <stdio.h> int main(void) { for (int i=1; i<=10; i++) { printf(&quot;Bottle %d\n&quot;, i); } } ``` 在本章中,我们使用了 Qt5 中的字符串。