原文: 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

  1. #include <QTextStream>
  2. int main(void) {
  3. QTextStream out(stdout);
  4. QString a = "love";
  5. a.append(" chess");
  6. a.prepend("I ");
  7. out << a << endl;
  8. out << "The a string has " << a.count()
  9. << " characters" << endl;
  10. out << a.toUpper() << endl;
  11. out << a.toLower() << endl;
  12. return 0;
  13. }

在代码示例中,我们启动QString。 我们附加并添加一些其他文字。 我们打印字符串的长度。 最后,我们以大写和小写形式显示修改后的字符串。

  1. QString a = "love";

启动QString

  1. a.append(" chess");
  2. a.prepend("I ");

我们将文本附加和添加到初始字符串之前。 该字符串就地修改。

  1. out << a << endl;

终端上印有I love chess

  1. out << "The a string has " << a.count()
  2. << " characters" << endl;

count()方法返回字符串中的字符数。 length()size()方法是等效的。

  1. out << a.toUpper() << endl;
  2. out << a.toLower() << endl;

这两个方法返回字符串的大写和小写副本。 他们不修改字符串,而是返回新的修改后的字符串副本。

输出:

  1. $ ./basic
  2. I love chess
  3. The a string has 12 characters
  4. I LOVE CHESS
  5. i love chess

初始化字符串

QString可以通过多种方式初始化。

init.cpp

  1. #include <QTextStream>
  2. int main(void) {
  3. QTextStream out(stdout);
  4. QString str1 = "The night train";
  5. out << str1 << endl;
  6. QString str2("A yellow rose");
  7. out << str2 << endl;
  8. std::string s1 = "A blue sky";
  9. QString str3 = s1.c_str();
  10. out << str3 << endl;
  11. std::string s2 = "A thick fog";
  12. QString str4 = QString::fromLatin1(s2.data(), s2.size());
  13. out << str4 << endl;
  14. char s3[] = "A deep forest";
  15. QString str5(s3);
  16. out << str5 << endl;
  17. return 0;
  18. }

我们介绍了五种初始化QString的方法。

  1. QString str1 = "The night train";

这是在计算机语言中初始化字符串的传统方式。

  1. QString str2("A yellow rose");

这是启动QString的对象方式。

  1. std::string s1 = "A blue sky";
  2. QString str3 = s1.c_str();

我们有一个来自 C++ 标准库的字符串对象。 我们使用其c_str()方法来生成以空字符结尾的字符序列。 该字符数组(字符串的经典 C 表示形式)可以分配给QString变量。

  1. std::string s2 = "A thick fog";
  2. QString str4 = QString::fromLatin1(s2.data(), s2.size());

在这些代码行中,我们将标准 C++ 字符串转换为QString。 我们利用fromLatin1()方法。 它需要一个指向字符数组的指针。 指针通过std::stringdata()方法返回。 第二个参数是std::string的大小。

  1. char s3[] = "A deep forest";
  2. QString str5(s3);

这是一个 C 字符串; 它是一个字符数组。 QString构造器之一可以将char数组作为参数。

输出:

  1. $ ./init
  2. The night train
  3. A yellow rose
  4. A blue sky
  5. A thick fog
  6. A deep forest

访问字符串元素

QStringQChars的序列。 可以使用[]运算符或at()方法访问字符串的元素。

access.cpp

  1. #include <QTextStream>
  2. int main(void) {
  3. QTextStream out(stdout);
  4. QString a = "Eagle";
  5. out << a[0] << endl;
  6. out << a[4] << endl;
  7. out << a.at(0) << endl;
  8. if (a.at(5).isNull()) {
  9. out << "Outside the range of the string" << endl;
  10. }
  11. return 0;
  12. }

我们从特定的QString打印一些单独的字符。

  1. out << a[0] << endl;
  2. out << a[4] << endl;

我们打印字符串的第一个和第五个元素。

  1. out << a.at(0) << endl;

使用at()方法,我们检索字符串的第一个字符。

  1. if (a.at(5).isNull()) {
  2. out << "Outside the range of the string" << endl;
  3. }

如果我们尝试访问字符串字符范围之外的字符,则at()方法返回null

输出:

  1. $ ./access
  2. E
  3. e
  4. E
  5. Outside the range of the string

字符串长度

有三种获取字符串长度的方法。 size()count()length()方法。 所有人都做同样的事情。 它们返回指定字符串中的字符数。

length.cpp

  1. #include <QTextStream>
  2. int main(void) {
  3. QTextStream out(stdout);
  4. QString s1 = "Eagle";
  5. QString s2 = "Eagle\n";
  6. QString s3 = "Eagle ";
  7. QString s4 = "орел";
  8. out << s1.length() << endl;
  9. out << s2.length() << endl;
  10. out << s3.length() << endl;
  11. out << s4.length() << endl;
  12. return 0;
  13. }

我们得到四个字符串的大小。

  1. QString s2 = "Eagle\n";
  2. QString s3 = "Eagle ";

这两个字符串中的每个字符串都有一个白色字符。

  1. QString s4 = "орел";

此字符串由俄语字母组成。

输出:

  1. $ ./length
  2. 5
  3. 6
  4. 6
  5. 4

从输出中我们可以看到length()方法也计算了白色字符。

字符串构建

动态字符串构建使我们可以用实际值替换特定的控制字符。 我们使用arg()方法进行插值。

building.cpp

  1. #include <QTextStream>
  2. int main() {
  3. QTextStream out(stdout);
  4. QString s1 = "There are %1 white roses";
  5. int n = 12;
  6. out << s1.arg(n) << endl;
  7. QString s2 = "The tree is %1 m high";
  8. double h = 5.65;
  9. out << s2.arg(h) << endl;
  10. QString s3 = "We have %1 lemons and %2 oranges";
  11. int ln = 12;
  12. int on = 4;
  13. out << s3.arg(ln).arg(on) << endl;
  14. return 0;
  15. }

将要替换的标记以%字符开头。 下一个字符是指定自变量的数字。 一个字符串可以有多个参数。 arg()方法已重载,它可以接受整数,长数字,字符和QChar等。

  1. QString s1 = "There are %1 white roses";
  2. int n = 12;

%1是我们计划替换的标记。 我们定义了一个整数。

  1. out << s1.arg(n) << endl;

arg()方法采用整数。 %1标记被n变量的值替换。

  1. QString s2 = "The tree is %1 m high";
  2. double h = 5.65;
  3. out << s2.arg(h) << endl;

这三行对于一个双数执行相同的操作。 正确的arg()方法将被自动调用。

  1. QString s3 = "We have %1 lemons and %2 oranges";
  2. int ln = 12;
  3. int on = 4;
  4. out << s3.arg(ln).arg(on) << endl;

我们可以有多个控制字符。 %1引用第一个参数,%2引用第二个参数。 arg()方法在连续的链中调用。

输出:

  1. $ ./building
  2. There are 12 white roses
  3. The tree is 5.65 m high
  4. We have 12 lemons and 4 oranges

子串

在进行文本处理时,我们需要找到普通字符串的子字符串。 我们有left()mid()right()方法可供我们使用。

substrings.cpp

  1. #include <QTextStream>
  2. int main(void) {
  3. QTextStream out(stdout);
  4. QString str = "The night train";
  5. out << str.right(5) << endl;
  6. out << str.left(9) << endl;
  7. out << str.mid(4, 5) << endl;
  8. QString str2("The big apple");
  9. QStringRef sub(&str2, 0, 7);
  10. out << sub.toString() << endl;
  11. return 0;
  12. }

我们将使用这三种方法查找给定字符串的一些子字符串。

  1. out << str.right(5) << endl;

通过right()方法,我们获得str字符串的最右边五个字符。 将打印train

  1. out << str.left(9) << endl;

使用left()方法,我们获得str字符串的最左边九个字符。 将打印night

  1. out << str.mid(4, 5) << endl;

使用mid()方法,我们从第 4 个位置开始得到 5 个字符。 打印night

  1. QString str2("The big apple");
  2. QStringRef sub(&str2, 0, 7);

QStringRef类是QString的只读版本。 在这里,我们创建str2字符串一部分的QStringRef。 第二个参数是位置,第三个参数是子字符串的长度。

输出:

  1. $ ./substrings
  2. train
  3. The night
  4. night
  5. The big

遍历字符串

QStringQChars组成。 我们可以遍历QString以访问字符串的每个元素。

looping.cpp

  1. #include <QTextStream>
  2. int main(void) {
  3. QTextStream out(stdout);
  4. QString str = "There are many stars.";
  5. foreach (QChar qc, str) {
  6. out << qc << " ";
  7. }
  8. out << endl;
  9. for (QChar *it=str.begin(); it!=str.end(); ++it) {
  10. out << *it << " " ;
  11. }
  12. out << endl;
  13. for (int i = 0; i < str.size(); ++i) {
  14. out << str.at(i) << " ";
  15. }
  16. out << endl;
  17. return 0;
  18. }

我们展示了通过QString的三种方法。 在将字母打印到终端时,我们在字母之间添加空格字符。

  1. foreach (QChar qc, str) {
  2. out << qc << " ";
  3. }

foreach关键字是 C++ 语言的 Qt 扩展。 关键字的第一个参数是字符串元素,第二个参数是字符串。

  1. for (QChar *it=str.begin(); it!=str.end(); ++it) {
  2. out << *it << " " ;
  3. }

在此代码中,我们使用迭代器遍历字符串。

  1. for (int i = 0; i < str.size(); ++i) {
  2. out << str.at(i) << " ";
  3. }

我们计算字符串的大小,并使用at()方法访问字符串元素。

输出:

  1. $ ./looping
  2. T h e r e a r e m a n y s t a r s .
  3. T h e r e a r e m a n y s t a r s .
  4. T h e r e a r e m a n y s t a r s .

字符串比较

QString::compare()静态方法用于比较两个字符串。 该方法返回一个整数。 如果返回的值小于零,则第一个字符串小于第二个字符串。 如果返回零,则两个字符串相等。 最后,如果返回的值大于零,则第一个字符串大于第二个字符串。 “较少”是指字符串的特定字符在字符表中位于另一个字符之前。 比较字符串的方法如下:比较两个字符串的第一个字符; 如果它们相等,则比较以下两个字符,直到找到一些不同的字符或发现所有字符都匹配为止。

comparing.cpp

  1. #include <QTextStream>
  2. #define STR_EQUAL 0
  3. int main(void) {
  4. QTextStream out(stdout);
  5. QString a = "Rain";
  6. QString b = "rain";
  7. QString c = "rain\n";
  8. if (QString::compare(a, b) == STR_EQUAL) {
  9. out << "a, b are equal" << endl;
  10. } else {
  11. out << "a, b are not equal" << endl;
  12. }
  13. out << "In case insensitive comparison:" << endl;
  14. if (QString::compare(a, b, Qt::CaseInsensitive) == STR_EQUAL) {
  15. out << "a, b are equal" << endl;
  16. } else {
  17. out << "a, b are not equal" << endl;
  18. }
  19. if (QString::compare(b, c) == STR_EQUAL) {
  20. out << "b, c are equal" << endl;
  21. } else {
  22. out << "b, c are not equal" << endl;
  23. }
  24. c.chop(1);
  25. out << "After removing the new line character" << endl;
  26. if (QString::compare(b, c) == STR_EQUAL) {
  27. out << "b, c are equal" << endl;
  28. } else {
  29. out << "b, c are not equal" << endl;
  30. }
  31. return 0;
  32. }

我们将使用compare()方法进行区分大小写和不区分大小写的比较。

  1. #define STR_EQUAL 0

为了更好的代码清晰度,我们定义STR_EQUAL常量。

  1. QString a = "Rain";
  2. QString b = "rain";
  3. QString c = "rain\n";

我们将比较这三个字符串。

  1. if (QString::compare(a, b) == STR_EQUAL) {
  2. out << "a, b are equal" << endl;
  3. } else {
  4. out << "a, b are not equal" << endl;
  5. }

我们比较ab字符串,它们不相等。 它们的第一个字符不同。

  1. if (QString::compare(a, b, Qt::CaseInsensitive) == STR_EQUAL) {
  2. out << "a, b are equal" << endl;
  3. } else {
  4. out << "a, b are not equal" << endl;
  5. }

如果不区分大小写,则字符串相等。 Qt::CaseInsensitive使比较大小写不敏感。

  1. c.chop(1);

chop()方法从c字符串中删除最后一个字符。 现在bc字符串相等。

输出:

  1. $ ./comparing
  2. a, b are not equal
  3. In case insensitive comparison:
  4. a, b are equal
  5. b, c are not equal
  6. After removing the new line character
  7. b, c are equal

转换字符串

字符串通常需要转换为其他数据类型,反之亦然。 toInt()toFloat()toLong()是将字符串转换为整数,浮点数和长整数的三种QString方法。 (还有更多这样的方法。)setNum()方法将各种数字数据类型转换为字符串。 该方法已重载,并且自动调用了正确的方法。

Output

  1. #include <QTextStream>
  2. int main(void) {
  3. QTextStream out(stdout);
  4. QString s1 = "12";
  5. QString s2 = "15";
  6. QString s3, s4;
  7. out << s1.toInt() + s2.toInt() << endl;
  8. int n1 = 30;
  9. int n2 = 40;
  10. out << s3.setNum(n1) + s4.setNum(n2) << endl;
  11. return 0;
  12. }

在示例中,我们将两个字符串转换为整数并将其相加。 然后,我们将两个整数转换为字符串并将其连接起来。

  1. out << s1.toInt() + s2.toInt() << endl;

toInt()方法将字符串转换为整数。 我们添加两个转换为字符串的数字。

  1. out << s3.setNum(n1) + s4.setNum(n2) << endl;

在这种情况下,setNum()方法将整数转换为字符串。 我们连接两个字符串。

输出:

  1. $ ./converts
  2. 27
  3. 3040

字符

字符分为各种类别:数字,字母,空格和标点符号。 每个QString都由QChar组成。 QChar具有isDigit()isLetter()isSpace()isPunct()方法来执行作业。

letters.cpp

  1. #include <QTextStream>
  2. int main(void) {
  3. QTextStream out(stdout);
  4. int digits = 0;
  5. int letters = 0;
  6. int spaces = 0;
  7. int puncts = 0;
  8. QString str = "7 white, 3 red roses.";
  9. foreach(QChar s, str) {
  10. if (s.isDigit()) {
  11. digits++;
  12. } else if (s.isLetter()) {
  13. letters++;
  14. } else if (s.isSpace()) {
  15. spaces++;
  16. } else if (s.isPunct()) {
  17. puncts++;
  18. }
  19. }
  20. out << QString("There are %1 characters").arg(str.count()) << endl;
  21. out << QString("There are %1 letters").arg(letters) << endl;
  22. out << QString("There are %1 digits").arg(digits) << endl;
  23. out << QString("There are %1 spaces").arg(spaces) << endl;
  24. out << QString("There are %1 punctuation characters").arg(puncts) << endl;
  25. return 0;
  26. }

在示例中,我们定义了一个简单的句子。 我们将计算句子中的数字,字母,空格和标点符号的数量。

  1. int digits = 0;
  2. int letters = 0;
  3. int spaces = 0;
  4. int puncts = 0;

我们为每个字符类别定义一个整数变量。

  1. QString str = "7 white, 3 red roses.";

这是要检查的句子。

  1. foreach(QChar s, str) {
  2. if (s.isDigit()) {
  3. digits++;
  4. } else if (s.isLetter()) {
  5. letters++;
  6. } else if (s.isSpace()) {
  7. spaces++;
  8. } else if (s.isPunct()) {
  9. puncts++;
  10. }
  11. }

我们使用foreach关键字来浏览QString。 每个元素都是QChar。 我们使用QChar类的方法来确定字符的类别。

  1. out << QString("There are %1 characters").arg(str.count()) << endl;
  2. out << QString("There are %1 letters").arg(letters) << endl;
  3. out << QString("There are %1 digits").arg(digits) << endl;
  4. out << QString("There are %1 spaces").arg(spaces) << endl;
  5. out << QString("There are %1 punctuation characters").arg(puncts) << endl;

使用字符串插值,我们将数字打印到终端。

输出:

  1. $ ./letters
  2. There are 21 characters
  3. There are 13 letters
  4. There are 2 digits
  5. There are 4 spaces
  6. There are 2 punctuation characters

修改字符串

某些方法(例如toLower()方法)返回原始字符串的新修改副本。 其他方法可就地修改字符串。 我们将介绍其中的一些。

modify.cpp

  1. #include <QTextStream>
  2. int main(void) {
  3. QTextStream out(stdout);
  4. QString str = "Lovely";
  5. str.append(" season");
  6. out << str << endl;
  7. str.remove(10, 3);
  8. out << str << endl;
  9. str.replace(7, 3, "girl");
  10. out << str << endl;
  11. str.clear();
  12. if (str.isEmpty()) {
  13. out << "The string is empty" << endl;
  14. }
  15. return 0;
  16. }

我们描述了四种就地修改字符串的方法。

  1. str.append(" season");

append()方法在字符串的末尾添加一个新字符串。

  1. str.remove(10, 3);

remove()方法从位置 10 开始从字符串中删除 3 个字符。

  1. str.replace(7, 3, "girl");

replace()方法用指定的字符串替换从7位置开始的3字符。

  1. str.clear();

clear()方法清除字符串。

输出:

  1. $ ./modify
  2. Lovely season
  3. Lovely sea
  4. Lovely girl
  5. The string is empty

在本章中,我们使用了 Qt5 中的字符串。

对齐字符串

拥有整洁的输出是常见的要求。 我们可以使用leftJustified()rightJustified()方法来对齐字符串。

right_align.cpp

  1. #include <QTextStream>
  2. int main(void) {
  3. QTextStream out(stdout);
  4. QString field1 = "Name: ";
  5. QString field2 = "Occupation: ";
  6. QString field3 = "Residence: ";
  7. QString field4 = "Marital status: ";
  8. int width = field4.size();
  9. out << field1.rightJustified(width, ' ') << "Robert\n";
  10. out << field2.rightJustified(width, ' ') << "programmer\n";
  11. out << field3.rightJustified(width, ' ') << "New York\n";
  12. out << field4.rightJustified(width, ' ') << "single\n";
  13. return 0;
  14. }

该示例将字段字符串向右对齐。

  1. int width = field4.size();

我们计算最宽字符串的大小。

  1. out << field1.rightJustified(width, ' ') << "Robert\n";

rightJustified()方法返回具有width字符的字符串。 如果字符串较短,则其余部分将使用提供的字符填充。 在我们的情况下,它是一个空格字符。

输出:

  1. $ ./right_align
  2. Name: Robert
  3. Occupation: programmer
  4. Residence: New York
  5. Marital status: single

转义字符

Qt5 具有toHtmlEscaped()方法,该方法将纯文本字符串转换为将 HTML 元字符<>&"替换为 HTML 命名实体的 HTML 字符串。

  1. $ cat cprog.c
  2. #include <stdio.h>
  3. int main(void) {
  4. for (int i=1; i<=10; i++) {
  5. printf("Bottle %d\n", i);
  6. }
  7. }

此 C 包含 HTML 元字符。

html_escape.cpp

  1. #include <QTextStream>
  2. #include <QFile>
  3. int main(void) {
  4. QTextStream out(stdout);
  5. QFile file("cprog.c");
  6. if (!file.open(QIODevice::ReadOnly)) {
  7. qWarning("Cannot open file for reading");
  8. return 1;
  9. }
  10. QTextStream in(&file);
  11. QString allText = in.readAll();
  12. out << allText.toHtmlEscaped() << endl;
  13. file.close();
  14. return 0;
  15. }

该示例读取一个 C 程序,并将元字符替换为其命名的实体。

输出:

  1. $ ./html_escape
  2. #include <stdio.h>
  3. int main(void) {
  4. for (int i=1; i<=10; i++) {
  5. printf(&quot;Bottle %d\n&quot;, i);
  6. }
  7. }

在本章中,我们使用了 Qt5 中的字符串。