Qt扫盲-QString使用总结


这里是我对帮助文档的一些理解,再复习复习一下之前的知识点。
我把文字分成了两部分,一半是给喜欢了解一下原理的,一部分是直接上手就行的。

一、概述

QString 是Qt 的一种基础数据类型,也是对字符串的一个封装。其实他的操作和标准库的std::string字符串的基本是一致的。但是还是有些区别。

QString 存储以数据长度为16位2字节 QChar类型的字符串,也是说每个字符类型是 QChar ,其中每个 QChar 对应于一个UTF-16 代码。(如果代码值高于 65535 的 Unicode 字符使用两个连续的 QChar来存储)这其实和 c++标准库的std::string使用一致,但是std::string的字符是char类型,8位一字节长度(用的Utf-8)。这里我们知道QString 和 std::string编码格式不一样,不能直接相互操作,得转码后才能用哦

Unicode 是一种国际标准,支持当今使用的大多数书写系统。是一种可变长度字符编码。它可以用来表示Unicode标准中的任何字符。会将一个码位编码为 1 到 4 个字节。它是 US-ASCII (ANSI X3.4-1986) 和 Latin-1 (ISO 8859-1) 的超集,所有 US-ASCII/Latin-1 字符都位于相同的代码位置。也就是说Unicode包括了 上述位置的编码

QString在内部实现的时候 使用隐式共享(写入时复制)来减少内存使用并避免不必要的数据复制。这也有助于减少存储 16 位字符而不是 8 位字符的固有开销(QChar 比 char 空间大)。
隐式共享可以参考我之前的博文: Qt扫盲–隐式共享基本原理

除了QString,Qt还提供了QByteArray类来存储原始字节和传统的8位“0”终止字符串(也即是char类型字符串)。在大多数情况下,QString 是您想要使用的类。它在整个Qt API中使用,Unicode支持确保您的应用程序易于翻译,如果您想在某个时候扩展应用程序市场。QByteArray 适合的两种主要情况是需要存储原始二进制数据时,以及内存保护至关重要时(在嵌入式系统中)。

二、初始化字符串

1、极速版

    //不带参构造
    QString str;
    
    //从const char * 字面量字符串构造
    QString str_1 = "dfdsfsd";
    
    //拷贝
    QString str_2 = str_1;

    //带参构造
    QString str_3();

    //从const char * 字面量字符串构造
    QString str_4("fdfsfs");
    
    //从QChar 数组构造
    static const QChar data[4] = { 'u', 'y', 0x10e3, 'd' };
    QString str_5(data, 4);

    //从QCahr构造
    QString str_6(QChar('&'));

    qDebug()<<str<<str_1<<str_2<<str_3<<str_4<<str_5<<str_6;

// 输出
// "" "dfdsfsd" "dfdsfsd" true "fdfsfs" "uy?d" "&"

2、原理版

初始化字符串有些方式?
当然看构造函数,QString 是类,那肯定就是构造函数初始化啦
在这里插入图片描述
帮助文档的推荐的三种写法

    1. 用常量字符串初始化 const char *
QString str = "Hello";
QString str1 = QString::fromUtf8("Hello"); //显然一般情况不用,第一种更简单

我们把 const char * 转成 QString 就可以用 fromUtf8() 方法。在所有采用 const char * 参数的 QString 函数中,const char * 被解释为以 UTF-8 编码的经典 C 样式“\0”结尾字符串。const char * 参数为 nullptr(空) 是合法的。但是尽量别用空指针。

    1. QChar 数组初始化
static const QChar data[4] = { 0x0055, 0x006e, 0x10e3, 0x03a3 };
QString str(data, 4);

QString 会用 QChar 数组的深拷贝,也就是说str和data没有共享内存(如果出于性能原因,您不想创建字符数据的深拷贝,请改用 QString::fromRawData() )

    1. 先分配再改值
QString str;
str.resize(4);

str[0] = QChar('U');
str[1] = QChar('n');
str[2] = QChar(0x10e3);
str[3] = QChar(0x03a3);

这种方法是使用 resize() 设置字符串的大小,并初始化每个字符的数据字符。QString 使用从 0 开始的索引,就像C++数组一样。要访问特定索引位置的字符,可以使用运算符 [ ] 在非常量字符串上。

三、操作字符串

1、极速版

1. 增加

对字符串的进行增操作,主要有下面这些

QString str = "and";
str.prepend("rock ");     	// str == "rock and"
str.append(" roll");        // str == "rock and roll"
str += " dsfsd";				// str == "rock and roll dsfsd"
str = str + QString(" fdsffsd") // str == "rock and roll dsfsd" fdsffsd

2. 删除

remove 函数还有好几种,支持正则表达式移除,下面是常用的几种

QString str = "AAA BBB CCC DDD AABBCC";
str = str.remove("AA");     	// str == "A BBB CCC DDD BBCC"
str = str.remove(4,4);			// str == "A BBC DDD BBCC"
str.clear();					// str == ""
str = "ccs";
str = "";						//重置为空字符串
str.resize(0)					// str == "" 重置长度为0的字符串

//去除首尾所有空白字符,空白字符包括'\t', '\n', '\v', '\f', '\r', ' '.
QString str = "  lots\t of\nwhitespace\r\n ";
str = str.trimmed();
// str == "lots\t of\nwhitespace"

//去除 多余空白字符,首尾全部去掉,每个序列的内部空格多余空白符替换为一个空格号。
QString str = "  lots\t of\nwhitespace\r\n ";
str = str.simplified();
// str == "lots of whitespace";

3. 修改

常用的就是替换,也是支持正则匹配替换的

QString str = "AAA BBB CCC DDD AABBCC";

//replace 方法
str = str.replace("AA", "哈哈哈");     	// str == "哈哈哈A BBB CCC DDD 哈哈哈BBCC"
str = str.replace('B','~');			// str == "哈哈哈A ~~~ CCC DDD 哈哈哈~~CC"

//索引修改
str[2] = '+'				// str = "哈哈+A ~~~ CCC DDD 哈哈哈~~CC"

//大小写转换
QString str = "TeXt";
str = str.toUpper();        // str == "TEXT"
str = str.toLower();		// str == "text"

4. 插入

QString str = "Meal";
str.insert(1, QString("ontr"));
// str == "Montreal"

QString str;
str = "%1 %2";

str.arg("%1f", "Hello");        // returns "%1f Hello"
str.arg("%1f").arg("Hello");    // returns "Hellof %2"

str = "%1%2%3";
str.arg("Hello").arg(50).arg(20); // returns "Hello5020"

5. 转换

//数字转字符串
QString str;
str.setNum(1234);       // str == "1234"

long a = 63;
QString s = QString::number(a, 16);             // s == "3f"
QString t = QString::number(a, 16).toUpper();     // t == "3F"

//字符串转数字格式
QString str = "1234.56";
double val = str.toDouble();   // val == 1234.56

bool ok;
double d;

d = QString( "1234.56e-02" ).toDouble(&ok); // ok == true, d == 12.3456
d = QString( "1234.56e-02 Volt" ).toDouble(&ok); // ok == false, d == 0

2、原理版

如果你事先知道一个 QString 将包含多少个字符,你可以调用 reserve() 函数来预先分配一定量的内存。我们可以也可以调用 capacity() 来找出 QString 实际分配了多少内存。

replace()remove() 函数的前两个参数是开始擦除的位置和应该擦除的字符数。如果要将特定子字符串的所有匹配项替换为另一个子字符串,请使用双参数 replace() 的重载函数。

如果要删除 QString 两端的空格,请使用 trimmed() 函数。
如果要删除两端的空格,并将字符串中的多个连续空格替换为单个空格字符,请使用 simplified()

如果要查找 QString 中特定字符或子字符串的所有匹配项,请使用 indexOf()lastIndexOf() 函数。前者从给定的索引位置开始向前搜索,后者向后搜索。如果找到字符或子字符串,两者都返回它的索引位置;否则,它们返回 -1。例如,下面是一个典型的循环,用于查找特定子字符串的所有匹配项:

  QString str = "We must be <b>bold</b>, very <b>bold</b>";
  int j = 0;

  while ((j = str.indexOf("<b>", j)) != -1) {
      qDebug() << "Found <b> tag at index position" << j;
      ++j;
  }

QString 提供了许多函数,用于将数字转换为字符串和字符串转换为数字。setNum() 函数、number() 静态函数和 toInt()toDouble() 和类似函数toDouble() 这类转换函数还有校验是否检验成功的功能

要获取字符串的大写或小写形式,请使用 toUpper()toLower()

我们可以使用 split() 函数将字符串拆分为字符串列表 QStringList 形式,这个split函数还可以选择是否过滤空字符串之类的。并使用 QStringList::join() 将字符串列表连接到带有可选分隔符的单个字符串中。可以使用 QStringList::filter() 函数从包含特定子字符串或与特定 QRegExp 匹配的字符串列表中获取字符串列表。

  QString str = "a,,b,c";

  QStringList list1 = str.split(',');
  // list1: [ "a", "", "b", "c" ]

  QStringList list2 = str.split(',', QString::SkipEmptyParts);
  // list2: [ "a", "b", "c" ]

  QStringList list;
  list << "Bill Murray" << "John Doe" << "Bill Clinton";

  QStringList result;
  result = list.filter("Bill");
  // result: ["Bill Murray", "Bill Clinton"]

四、查询字符串

对于只是读取字符串的话,用 at() 方法 比 [] 更快,因为 [] 是深拷贝,at只是浅拷贝或者,使用 left()、right() 或 mid() 函数一次提取多个字符。

QString str;

for (int i = 0; i < str.size(); ++i) 
{
	if (str.at(i) >= QChar('a') && str.at(i) <= QChar('f'))
		qDebug() << "Found character in range [a-f]";
}

  QString x = "Pineapple";
  QString y = x.left(4);      // y == "Pine"
  
  QString x = "Pineapple";
  QString y = x.right(5);      // y == "apple"

  QString x = "Nine pineapples";
  QString y = x.mid(5, 4);            // y == "pine"
  QString z = x.mid(5);               // z == "pineapples"

QString 可以嵌入“0”字符 (QChar::Null)。size() 函数始终返回整个字符串的大小,包括嵌入的“0”字符。
调用 resize() 函数后,新分配的字符具有未定义的值。要将字符串中的所有字符设置为特定值,请使用 fill() 函数。
QString 提供了数十种重载,旨在简化字符串的使用。例如,如果要将 QString 与字符串文本进行比较,则可以编写如下代码,它将按预期工作:

QString str;

if (str == "auto" || str == "extern"
	|| str == "static" || str == "register")
{
	// ...
}

QString str = "World";
int n = str.size();         // n == 5
str.data()[0];              // returns 'W'
str.data()[4];              // returns 'd'
  • startsWith()endsWith() 查看 字符串是不是以特定的子字符串开始还是结束。
  • contains() 函数来检查 字符串 是否包含特定字符或子字符串。用 count()来统计特定字符或子字符串在字符串中出现的次数。
  • 可以使用重载运算符(如运算符 < 、<= 、== 、>= 等来比较 字符串大小。请注意,比较基于字符的数字 Unicode 值大小。它非常快,但不是人类所期望的。
  • QString::localeAwareCompare() 静态函数来 排序用户界面字符串 其实就是本地字符串比较。
  • data()constData()。这些函数返回指向 QChar 数据开头的指针。但是指针是保证仍然有效,除非非 const QString函数被调用。这个就失效了。
QString str = "Bananas";
str.startsWith("Ban");     // returns true
str.startsWith("Car");     // returns false

五、字符串格式转换

QString 提供了以下三个函数,这些函数将字符串的 const char * 版本作为 QByteArray:toUtf8()toLatin1()toLocal8Bit()

  • toLatin1() 返回一个拉丁语-1 (ISO 8859-1) 编码的 8 位字符串。
  • toUtf8() 返回一个 UTF-8 编码的 8 位字符串。UTF-8 是 US-ASCII (ANSI X3.4-1986) 的超集,它通过多字节序列支持整个 Unicode 字符集。
  • toLocal8Bit() 使用系统的本地编码返回一个 8 位字符串。

要从这些编码之一进行转换,QString 提供了 fromLatin1()、fromUtf8() 和 fromLocal8Bit()。其他编码通过 QTextCodec 类受支持。

如上所述,QString 提供了许多函数和运算符,使得与 const char * 字符串的互操作变得容易。但此功能是一把双刃剑:如果所有字符串都是 US-ASCII 或 Latin-1,它会使 QString 更方便使用,但始终存在使用错误的 8 位编码完成从 const char * 到const char * 的隐式转换的风险。若要最大程度地降低这些风险,可以通过定义以下两个预处理器符号来关闭这些隐式转换:

  • QT_NO_CAST_FROM_ASCII:禁用从 C 字符串文本和指针到 Unicode 的自动转换。
  • QT_RESTRICTED_CAST_FROM_ASCII: 允许从 C 字符和字符数组自动转换,但禁用从字符指针到 Unicode 的自动转换。
  • QT_NO_CAST_TO_ASCII:禁用从 QString 到 C 字符串的自动转换。

为应用程序全局定义这些预处理器符号的一种方法是将以下条目添加到 qmake 项目文件中:

DEFINES += QT_NO_CAST_FROM_ASCII \
             QT_NO_CAST_TO_ASCII

然后,您需要显式调用 fromUtf8()、fromLatin1() 或 fromLocal8Bit() 来从 8 位字符串构造 QString,或使用轻量级 QLatin1String 类,例如:

QString url = QLatin1String(“http://www.unicode.org/”);

同样,您必须显式调用 toLatin1()、toUtf8() 或 toLocal8Bit() 才能将 QString 转换为 8 位字符串。(其他编码通过 QText编解码器类受支持。

六、Null 字符串和 Empty 字符串的区别

由于历史原因,QString区分一个空字符串和一个空字符串。一个空字符串的字符串初始化使用QString默认的构造函数或通过构造函数(const char *) 0。一个空字符串是任何字符串大小为0。 一个空字符串总是空的,但一个空字符串不一定是零:

  QString().isNull();               // returns true
  QString().isEmpty();              // returns true

  QString("").isNull();             // returns false
  QString("").isEmpty();            // returns true

  QString("abc").isNull();          // returns false
  QString("abc").isEmpty();         // returns false

所有的功能除了 isNull() 把null字符串一样空字符串。例如, toUtf8 () 、constData() 返回一个有效的指针(不是nullptr) ’ \ 0 '字符为空字符串。建议始终使用 isEmpty() 函数,避免 isNull ()

七、字符串参数格式化

在QString的成员函数里面,有很多需要字符串参数格式化 比如(arg(), number())函数,其实是就是把这些数字转字符串,有科学计数法的形式和浮点数那种形式。

格式化含义
eformat as [-]9.9e[±]999
Eformat as [-]9.9E[±]999
f把数字±9.9 转换成 ±9.9
guse e or f format, 看哪种更简洁
Guse E or f format, 看哪种更简洁

精度也是指定的参数格式。的“e”、“e”和“f”格式,精度表示小数点后的位数数。‘g’和‘g’格式、精度表示有效数字的最大数量。其实就是科学计数法那种形式。

八、更高效的字符串构造

许多字符串在编译时是已知的。但是琐碎的构造函数 QString(“Hello”)将复制字符串的内容,将内容视为 Latin-1。为了避免这种情况,可以使用QStringLiteral宏在编译时直接创建所需的数据。从文本构造 QString 不会在运行时产生任何开销。
效率稍低的方法是使用 QLatin1String。此类包装 C 字符串文本,在编译时预先计算其长度,然后可用于与 QString 进行比较并转换为 QString,而不是常规 C 字符串文本。使用 QString ‘+’ 运算符,可以轻松地从多个子字符串构造复杂的字符串。
你经常会写这样的代码:

QString foo;
QString type = "long";

foo->setText(QLatin1String("A") + type + QLatin1String("B"));

if (foo.startsWith("(" + type + ") dd"))
          ...

这两种字符串结构都没有错,但存在一些隐藏的低效率。从Qt 4.6开始,您可以消除它们。
首先,多次使用“+”运算符通常意味着多个内存分配。连接 n 个子字符串(其中 n > 2)时,可以有多达 n - 1 次对内存分配器的调用。
在Qt 4.6 中,添加了内部模板类 QStringBuilder 以及一些帮助程序函数。此类标记为内部,不会出现在文档中,因为您不应该在代码中实例化它。它的使用将是自动的,如下所述。该类可以在src/corelib/tools/qstringbuilder中找到.cpp如果你想看看它的话。QStringBuilder 使用表达式模板并重新实现“%”运算符,以便当您使用“%”而不是“+”进行字符串串联时,多个子字符串连接将被推迟,直到最终结果即将分配给 QString。此时,已知最终结果所需的内存量。然后调用一次内存分配器以获取所需的空间,并将子字符串逐个复制到其中。通过内联和减少引用计数来获得额外的效率(从 QStringBuilder 创建的 QString 通常具有 ref 计数 1,而 QString::append() 需要额外的测试)。有两种方法可以访问这种改进的字符串构造方法。简单的方法是在您想要使用它的任何位置包含 QStringBuilder,并在连接字符串时使用 ‘%’ 运算符而不是 ‘+’:就是推荐下面这种写法,用 % 代替 +

 #include <QStringBuilder>

QString hello("hello");
QStringRef el(&hello, 2, 3);
QLatin1String world("world");
QString message =  hello % el % world % QChar('!');

一种更全局的方法,也是最方便但不完全兼容源代码的方法,是在 .pro 文件中定义:

DEFINES *= QT_USE_QSTRINGBUILDER

并且“+”将在任何地方自动执行为QStringBuilder 的 “%”。

九、最大大小和出现内存不足的情况

这个了解了解就好。

QString 的当前版本的大小限制为略低于 2 GB(231 字节)。确切的值取决于体系结构,因为它取决于管理数据块所需的开销,但不超过 32 个字节。原始数据块还受到当前版本中使用 int 类型的限制为 2 GB 减去 1 字节。由于 QString 每个字符使用两个字节,因此在一个 QString 中转换为不到 2^30 个字符。
如果内存分配失败,QString 将抛出 std::bad_alloc 异常。Qt容器中的内存不足情况是Qt抛出异常的唯一情况。
请注意,操作系统可能会对持有大量已分配内存的应用程序施加进一步限制,尤其是大型连续块。此类注意事项、此类行为的配置或任何缓解措施都不在Qt API的范围之内。

  • 4
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: QStringList 是 Qt 中的一个类,它提供了一个动态的数组,其中的元素都是 QString 类型的字符串。 你可以使用这个类来储存和处理多个字符串。例如,你可以使用 QStringList::append() 方法来往数组里添加新的字符串,或者使用 QStringList::at() 方法来访问数组中的特定元素。 QStringQt 中的另一个类,它表示一个 Unicode 字符串。你可以使用 QString 来储存和处理文本数据。QString 提供了许多方法,可以让你对字符串进行操作,例如搜索、替换、拼接等。 总的来说,QStringList 和 QString 都是 Qt 中非常常用的类,你可以使用它们来处理多个字符串或者单个字符串。 ### 回答2: Qt中的QStringList和QString数组都是用来存储字符串的数据结构。区别在于QStringList更适合处理多个字符串的情况,而QString数组适合处理固定长度的字符串数组。 QStringList是Qt中提供的一个类,用于存储多个字符串。它可以动态增加和删除字符串,并且提供了一系列方便的方法来处理字符串列表,比如按照索引访问、循环遍历、排序、搜索等。QStringList可以实现动态管理和操作字符串集合,非常适用于需要频繁修改和操作多个字符串的场景,比如文件路径列表、选项列表等。 QString数组是一个固定长度的存储字符串的数组。与普通的C风格字符串数组不同,QString数组提供了更方便和安全的操作接口,可以动态修改数组中的字符串。由于是固定长度的数组,一旦分配空间就无法动态改变长度。QString数组适用于需要存储固定长度的字符串集合,比如固定的标识符列表、预定义的字符串数组等。 总结来说,QStringList适合处理动态的、可变长度的字符串集合,而QString数组适合处理静态的、固定长度的字符串数组。根据具体的应用场景和需求,选择合适的数据结构可以提高代码的效率和可维护性。 ### 回答3: Qt中的QStringList和QString数组都是用来存储字符串的数据类型。 QStringList是Qt中的一个类,它可以存储多个字符串,并且提供了一些方法来方便地操作这些字符串。通过QStringList,我们可以实现存储、添加、删除、查找等操作。例如,我们可以使用QStringList的append()方法向列表中添加字符串,使用removeAll()方法删除指定的字符串,使用contains()方法检查列表中是否包含某个字符串等。 QString数组则是一个固定大小的数组,每个元素都是一个QString类型的字符串。一旦创建了该数组,它的大小就无法再改变。我们可以使用下标来访问数组中的元素。例如,如果我们有一个QString数组arr,可以通过arr[0]访问第一个元素,arr[1]访问第二个元素,依此类推。 不同之处在于QStringList是一个可变大小的列表,可以根据需要动态地添加或删除其中的元素,而QString数组是一个固定大小的数组,一旦创建就不能再改变其大小。所以在对字符串进行频繁的增删操作时,使用QStringList更加方便。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

太阳风暴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值