奇牛Qt05 Qt字符串QString —— 奇牛+gemini
奇牛Qt05 Qt字符串QString —— 奇牛+gemini
1. 核心概述
- 头文件:
#include <QString> - 模块:
QT += core - 基本功能:Qt 框架中用于处理文本的通用字符串类型。它的使用方式与标准库的
std::string非常相似,但在底层设计和字符编码上有所不同。
1.1 QString 与 std::string 的区别
- 字符编码:
QString内部的每个字符都是QChar类型(16位,使用 UTF-16 编码),对多语言(如中文)支持极佳;而std::string存储的是char类型(8位,通常使用 UTF-8 编码)。 - 内存机制(隐式共享 / 写时复制):
QString内部实现了隐式共享(Copy-on-Write),以减少内存开销并避免不必要的数据深拷贝。Qt 的许多其他类(如QByteArray,QBrush,QDir,QBitmap等)也都采用了这一机制。
写时复制原理详解:
QString str1 = "nameless"; // 初始化
QString str2 = str1; // 拷贝构造(浅拷贝)
// 此时 str1 和 str2 指向同一个底层数据结构。该结构包含字符串内容和“引用计数器”。此时计数器值为 2。
str2[2] = 'a';
// 发生修改!触发“深拷贝”。str2 会指向一个全新克隆的数据结构(计数器为 1),
// 同时 str1 指向的原结构计数器减为 1。在此新结构上完成修改。
str2[2] = 'm';
// 再次修改 str2。由于此时 str2 的数据结构没有被共享(计数器为 1),因此不会发生任何拷贝动作。
str1 = str2;
// str1 放弃原结构(原结构计数器变为 0,内存被自动释放)。
// 随后 str1 重新指向 str2 的结构,该结构的引用计数再次变为 2。
2. 常用 API 详解与使用格式
2.1 初始化与打印
语法格式:支持赋值、构造函数、拷贝构造等多种初始化方式。
示例代码:
QString str1 = "nameless";
QString str2 = str1;
QString str3("nameless");
QString str4(str1);
qDebug() << str1 << str2 << str3 << str4;
2.2 判空
函数原型:bool isEmpty() const;
讲解:当字符串长度为 0(即没有字符,如 "" 或未初始化的默认对象)时返回 true,否则返回 false。
示例代码:
QString str1; // 未初始化,isEmpty() 为 true
QString str2 = ""; // 空串,isEmpty() 为 true
QString str3 = " "; // 包含一个空格,isEmpty() 为 false
2.3 获取字符串长度
函数原型:
int size() const;int length() const;int count() const;
讲解:这三个方法在 QString 中完全等效,皆返回字符串中的字符个数。一个汉字在 QString 中被计为一个字符(一单位长度/QChar)。
示例代码:
QString str1 = "nameless";
qDebug() << str1.size() << str1.length() << str1.count();
// 输出:8 8 8
2.4 添加与插入数据
函数原型:
- 尾部追加:
QString& append(const QString &str);(或使用重载运算符+=) - 任意位置插入:
QString& insert(int position, const QString &str);
讲解:insert() 的第一个参数为插入的索引位置。若传入的索引值超过当前字符串最大长度,内部会自动补充空格;若索引为负数,则插入失败,不产生任何效果。
示例代码:
// 1. 尾部追加
QString str1 = "你是谁啊?";
str1 += "我是";
str1.append("nameless");
qDebug() << str1; // "你是谁啊?我是nameless"
// 2. 任意位置插入
QString str2 = "你是谁啊?咕咕嘎嘎!";
str2.insert(5, "我");
str2.insert(6, "是凑企鹅!");
qDebug() << str2; // "你是谁啊?我是凑企鹅!咕咕嘎嘎!"
// 3. .insert索引值过大补空格;索引为负插入失败,无效果
QString str3 = "你是谁啊?";
str3.insert(15, "我是香企鹅!");
str3.insert(-1, "咕咕嘎嘎!");
qDebug() << str3; // "你是谁啊? 我是香企鹅!"
2.5 替换字符串
函数原型:QString& replace(const QString &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
讲解:将字符串中所有出现的 before 子串替换为 after。第三个参数控制是否区分大小写:
Qt::CaseSensitive(默认):区分大小写。Qt::CaseInsensitive:不区分大小写。
示例代码:
QString str1 = "A! a! o!";
QString str2 = "你是谁啊?我是nameless";
// 默认区分大小写
str1.replace("A", "欸");
qDebug() << str1; //"欸! a! o!"
// 传入 Qt::CaseInSensitive, 替换时不缺分大小写
str2.replace("NAMELESS", "凑企鹅", Qt::CaseInsensitive);
qDebug() << str2; // "你是谁啊?我是凑企鹅"
2.6 修改指定位置字符
语法格式:通过下标运算符 str[index] = QChar; 进行修改。
讲解:可以像操作数组一样修改指定索引的字符。如果指定的序号太大,Qt 会自动在中间补充空格以扩充长度。
示例代码:
QString str1 = "123456";
str1[0] = 'A'; // 变为 "A23456"
str1[7] = '7'; // 索引7超出当前长度,自动补空格,变为 "A23456 7"
2.7 数据类型转换
2.7.1 转换为数值(整数/浮点数)
函数原型:
int toInt(bool *ok = nullptr, int base = 10) const;double toDouble(bool *ok = nullptr) const;
讲解:
ok:转换状态指针。转换成功则被赋值为true,失败则为false。base:进制基数(如 10 进制、16 进制)。默认为 10,若设为 0 则自动根据字符串前缀(如0x)解析。- 同类方法还包括
toFloat(),toShort()等,用法完全一致。
示例代码:
// 1. 转换为整数
QString str1 = "365abc";
bool ret;
int num = str1.toInt(&ret, 10); // 包含非数字字符,ret 将为 false,转换失败
if (ret) {
qDebug() << "转换成功:" << num;
} else {
qDebug() << "转换失败";
}
QString str2 = "365";
num = str2.toInt(&ret, 16); // 按16进制转换
num = str2.toInt(); // 默认按10进制转换
// 2. 转换为浮点数
QString str3 = "3.14a";
double dNum = str3.toDouble(&ret); // 失败,含有字符 'a'
str3 = "3.14";
dNum = str3.toDouble(); // 成功
2.7.2 转换为 C 风格字符串(char *)
函数原型:std::string toStdString() const;
讲解:由于标准库和 Qt 的字符串底层编码与结构不同,通常需要先通过 toStdString() 转换为 std::string,再通过 .c_str() 获取临时的 const char* 指针。
示例代码:
QString str1 = "A! a! o!";
const char* c_str1 = str1.toStdString().c_str();
std::cout << c_str1 << std::endl; // A! a! o!
2.8 删除数据
函数原型:
- 按位置删除:
QString& remove(int position, int n); - 按子串删除:
QString& remove(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive); - 清空串:
void clear();
示例代码:
QString str = "123456";
str.remove(0, 2); // 从索引 0 开始,删除 2 个字符,结果为 "3456"
QString str2 = "Rock is rock lover";
str2.remove("rock"); // 默认区分大小写,只删除小写 "rock"
str2.remove("rock", Qt::CaseInsensitive); // 不区分大小写,全部删除
// 清空字符串
QString str3 = "床前明月光";
str3.clear(); // 变为空串,长度为 0
2.9 获取子字符串
函数原型:
- 指定范围截取:
QString mid(int position, int n = -1) const; - 头部截取:
QString left(int n) const; - 尾部截取:
QString right(int n) const;
讲解:
mid():从指定position开始截取n个字符。如果n为 -1(默认),则截取到字符串末尾。left(n):等价于mid(0, n),获取左侧n个字符。right(n):获取倒数最后n个字符。
示例代码:
QString str = "床前明月光";
QString s1 = str.mid(2); // 从索引2到结束 -> "明月光"
QString s2 = str.mid(2, 2); // 从索引2开始取2个字符 -> "明月"
QString s3 = str.left(2); // 取左边2个字符 -> "床前"
QString s4 = str.right(3); // 取右边3个字符 -> "明月光"
2.10 分割字符串
函数原型:QStringList split(const QString &sep) const;
讲解:使用分隔符 sep 将字符串切分成多个子串,并存入 QStringList 容器中。
示例代码:
QString str = "床前明月光 疑是地上霜 举头望明月 低头思故乡";
QStringList list = str.split(" "); // 按空格分割
int n = list.count();
for (int i = 0; i < n; i++)
{
qDebug() << list[i]; // 逐行输出每句诗
}

浙公网安备 33010602011771号