Qt4 中的字符串
最后修改于 2023 年 10 月 18 日
在本章中,我们将使用字符串。Qt4 有一个用于处理字符串的 QString
类。它非常强大,并且有许多方法。
QString
类提供一个 Unicode 字符串。它将字符串存储为 16 位 QChars。每个 QChar
对应一个 Unicode 4.0 字符。与许多其他编程语言中的字符串不同,QString
可以被修改。
第一个示例
在第一个例子中,我们将使用 QString
类的一些基本方法。
#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
。我们追加和预先添加一些额外的文本。我们打印字符串的长度。最后,我们以大写和小写打印修改后的字符串。
QString a = "love";
一个 QString
被初始化。
a.append(" chess"); a.prepend("I ");
我们向初始字符串追加和预先添加文本。字符串被原地修改。
out << a << endl;
“我爱国际象棋”被打印到终端。
out << "The a string has " << a.count() << " characters" << endl;
count
方法返回字符串中的字符数。length
和 size
方法是等效的。
out << a.toUpper() << endl; out << a.toLower() << endl;
这两种方法都返回字符串的大写和小写副本。它们不修改字符串,而是返回一个修改后的新副本。
$ ./basic I love chess The a string has 12 characters I LOVE CHESS i love chess
初始化字符串
QString
可以通过多种方式初始化。
#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::fromAscii(s2.data(), s2.size()); out << str4 << endl; char s3[] = "A deep forest"; QString str5(s3); out << str5 << endl; return 0; }
我们展示了初始化 QString 的五种方法。
QString str1 = "The night train";
这是一种在计算机语言中初始化字符串的传统方式。
QString str2("A yellow rose");
这是一种初始化 QString
的对象方式。
std::string s1 = "A blue sky"; QString str3 = s1.c_str();
我们有一个来自 C++ 标准库的字符串对象。我们使用它的 c_str
方法生成一个以 null 结尾的字符序列。这个字符数组,一个经典的 C 字符串表示,可以被分配给一个 QString
变量。
std::string s2 = "A thick fog"; QString str4 = QString::fromAscii(s2.data(), s2.size());
在这些代码行中,我们将一个标准 C++ 字符串转换为一个 QString。我们使用了 fromAscii
方法。它接受一个指向字符数组的指针。该指针是通过 std::string
的 data
方法返回的。第二个参数是 std::string
的大小。
char s3[] = "A deep forest"; QString str5(s3);
这是一个 C 字符串。它是一个字符数组。其中一个 QString
构造函数可以接受一个字符数组作为参数。
$ ./init The night train A yellow rose A blue sky A thick fog A deep forest
访问字符串元素
一个 QString
是一系列 QChars
。可以使用 []
运算符或 at
方法访问字符串的元素。
#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
中打印一些单独的字符。
out << a[0] << endl; out << a[4] << endl;
我们打印字符串的第一个和第五个元素。
out << a.at(0) << endl;
使用 at
方法,我们检索字符串的第一个字符。
if (a.at(5).isNull()) { out << "Outside the range of the string" << endl; }
如果我们要访问字符串字符范围之外的字符,则 at
方法将返回 null。
$ ./access E e E Outside the range of the string
字符串长度
有三种方法可以获取字符串的长度。size
,count
和 length
方法。所有方法都做同样的事情。它们返回指定字符串中的字符数。
#include <QTextStream> int main(void) { QTextStream out(stdout); QString s1 = "Eagle"; QString s2 = "Eagle\n"; QString s3 = "Eagle "; QString s4 = QString::fromUtf8("орел"); out << s1.length() << endl; out << s2.length() << endl; out << s3.length() << endl; out << s4.length() << endl; return 0; }
我们获取四个字符串的大小。
QString s2 = "Eagle\n"; QString s3 = "Eagle ";
这两个字符串中的每一个都包含一个空格字符。
QString s4 = QString::fromUtf8("орел");
此字符串由俄文字母组成。
$ ./length 5 6 6 4
从输出中我们可以看到 length
方法也计算了空格字符。最后一个字符串包含 Unicode 字母,其中每个字母存储为两个字符。
字符串插值
字符串插值是字符串的动态构建。它允许我们用实际值替换特定的控制字符。我们使用 arg
方法进行插值。
#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
方法被重载,它可以接受整数、长数字、字符和 QChars 等。
QString s1 = "There are %1 white roses"; int n = 12;
%1
是我们计划替换的标记。我们定义了一个整数。
out << s1.arg(n) << endl;
arg
方法接受一个整数。%1
标记被替换为 n
变量的值。
QString s2 = "The tree is %1 m high"; double h = 5.65; out << s2.arg(h) << endl;
这三行对双精度数做同样的事情。正确的 arg
方法被自动调用。
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
方法以连续链的形式被调用。
$ ./interpolation There are 12 white roses The tree is 5.65 m high We have 12 lemons and 4 oranges
子字符串
在进行文本处理时,我们需要找到普通字符串的子字符串。我们可以使用 left
、mid
和 right
方法。
#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; }
我们使用所有三种方法来查找给定字符串的一些子字符串。
out << str.right(5) << endl;
使用 right
方法,我们获取 str
字符串的最后五个字符。打印出“火车”。
out << str.left(9) << endl;
使用 left
方法,我们获取 str
字符串的前九个字符。打印出“夜晚”。
out << str.mid(4, 5) << endl;
使用 mid
方法,我们获取从第 4 个位置开始的五个字符。打印出“夜晚”。
QString str2("The big apple"); QStringRef sub(&str2, 0, 7);
QStringRef
类是 QString
的只读版本。这里我们创建一个 QStringRef
,它是 str2
字符串的一部分。第二个参数是位置,第三个是子字符串的长度。
$ ./substrings train The night night The big
循环遍历字符串
QString
由 QChars
组成。我们可以循环遍历 QString
以访问字符串的每个元素。
#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
的方法。我们在将字母打印到终端时,在字母之间添加一个空格字符。
foreach (QChar qc, str) { out << qc << " "; }
foreach
关键字是 C++ 语言的 Qt 扩展。该关键字的第一个参数是字符串元素,第二个参数是字符串。
for (QChar *it=str.begin(); it!=str.end(); ++it) { out << *it << " " ; }
在此代码中,我们使用迭代器遍历字符串。
for (int i = 0; i < str.size(); ++i) { out << str.at(i) << " "; }
我们计算字符串的大小,并使用 at
方法访问字符串元素。
$ ./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
静态方法用于比较两个字符串。该方法返回一个整数。如果返回的值小于零,则第一个字符串小于第二个字符串。如果它返回零,则两个字符串相等。最后,如果返回的值大于零,则第一个字符串大于第二个字符串。我们所说的“小于”是指字符串的特定字符在字符表中位于另一个字符之前。字符串的比较方式如下:比较两个字符串的第一个字符;如果它们相等,则比较接下来的两个字符,直到我们找到一些不同的字符或我们发现所有字符都匹配。
#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
方法进行区分大小写和不区分大小写的比较。
#define STR_EQUAL 0
为了更好地清晰代码,我们定义了 STR_EQUAL
常量。
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; }
我们比较 a
和 b
字符串,它们不相等。它们在第一个字符上有所不同。
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
使比较不区分大小写。
c.chop(1);
chop
方法从 c
字符串中删除最后一个字符。现在 b
和 c
字符串相等。
$ ./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
方法将各种数值数据类型转换为字符串。该方法被重载,正确的那个被自动调用。
#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; }
在该示例中,我们将两个字符串转换为整数并将它们相加。然后,我们将两个整数转换为字符串并将它们连接起来。
out << s1.toInt() + s2.toInt() << endl;
toInt
方法将字符串转换为整数。我们添加两个从字符串转换而来的数字。
out << s3.setNum(n1) + s4.setNum(n2) << endl;
在这种情况下,setNum
方法将一个整数转换为一个字符串。我们连接两个字符串。
$ ./converts 27 3040
字母
字符被分成不同的类别:数字、字母、空格和标点字符。每个 QString
由 QChars 组成。QChar
有 isDigit
、isLetter
、isSpace
和 isPunct
方法来完成这项工作。
#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; }
在该示例中,我们定义了一个简单的句子。我们计算句子中数字、字母、空格和标点字符的数量。
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++; } }
我们使用 foreach
关键字遍历 QString
。每个元素都是一个 QChar
。我们使用 QChar
类的方法来确定字符的类别。
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;
使用字符串插值,我们将数字打印到终端。
$ ./letters There are 21 characters There are 13 letters There are 2 digits There are 4 spaces There are 2 punctuation characters
修改字符串
某些方法(例如 toLower
方法)返回原始字符串的修改后的新副本。其他方法原地修改字符串。我们介绍了其中的一些方法。
#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; }
我们描述了四个原地修改字符串的方法。
str.append(" season");
append
方法在字符串的末尾添加一个新字符串。
str.remove(10, 3);
remove
方法从字符串中删除 3 个字符,从位置 10 开始。
str.replace(7, 3, "girl");
replace
方法将从位置 7
开始的 3
个字符替换为指定的字符串。
str.clear();
clear
方法清除字符串。
$ ./modify Lovely season Lovely sea Lovely girl The string is empty
对齐字符串
拥有一个整洁的输出是一个常见的需求。我们可以使用 leftJustified
和 rightJustified
方法来对齐我们的字符串。
#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; }
该示例将字段字符串向右对齐。
int width = field4.size();
我们计算最宽字符串的大小。
out << field1.rightJustified(width, ' ') << "Robert\n";
rightJustified
方法返回一个包含 width
个字符的字符串。如果字符串较短,则其余部分用提供的字符填充。在我们的例子中,它是一个空格字符。
$ ./rightalign Name: Robert Occupation: programmer Residence: New York Marital status: single
在本章中,我们使用了 Qt4 中的字符串。