一.字符编码
1.字符编码概述

QT解决不同编码相互转换问题,QT在存储是Unicode ,输出是编码进行转换
2.QString跨平台原理
原本是UTF-8,编译器是GBK(Windows终端是GBK,MAC、Linux是UTF-8),所以VSCode可以改成GBK
问题:怎么方便的更改(源码不变情况)
传统字符已经编码,QT字符(类:QChar,QString底层就是QChar)通过Unicode中转
UTF-8是QT中Unicode默认的编码,如果给入的是GBK,需要特殊的构造函数,否则乱码
原因:UTF-8有自己的构造函数,给的编码是GBK时,会使用UTF-8的编码,所以要自己设置一个构造函数

例如
QString str3 = QString::fromLocal8Bit("hello你好");
本地编码(GBK)的字符串转成 Qt 能正常显示的 QString,防止中文乱码
fromLocal8Bit的函数意思从本地 8bit 编码 转换
字符转换的网站:https://aichaxun.cn/unicode-char-lookup.html
二.QString的内存结构和写时拷贝
1.概念
空间传递:c++用指针/引用传递
QT自定义的容器类型:COW(写时拷贝),值传递
2.内存结构和写时拷贝深入解析
修改前一个空间,修改后另一个空间(实时拷贝)
QString内部结构和COW效果

初步初始化时,x1,x2指向同一个空间,当x2进行修改后x2有指向新空间(这叫做写时拷贝)
内存结构:

constData()返回的是QChar*的返回值,Datapointe是整个的地址
多数用constData的空间(数据空间)
写时拷贝:写入时再拷贝一份,x2指向新空间
注意:
更改过后,原空间是否继续维护
在读数据释放时的特点:x1释放了,但是x2继续指向该空间,所以给空间不消失

三.QString的常用方法

1.QString的构造方法和静态方法
标准C++的string也会用在QT中,但是与用户交接时一定是QString
静态成员函数返回值是QString
动态构造方法是qDebug的写法

仿照C语言sprintf写法,提出QString::asprintf用法,返回同样是字符串,但是该方法打印有双引号(工程不建议sprintf,容易越界)
2.常用类型结构转换
UTF-8字符风格转换
方法一:父子关系直接赋值
方法二:动态from方法

静态from方法转换,因为printf和qDebug同时使用,控制台优先级缘故,先打印"你好"

添加UTF-8字符时的效果
函数:
(1)QString::fromUtf8( , ) : 前者是空间名,后者是长度
(2)str1.toUtf8().constData()
toUtf8():把 QString 转成 UTF-8 字节数组
作用:将 QString 内部的 UTF-16 字符,转换成 UTF-8 编码的字节序列。
返回值:返回一个 QByteArray 类型的临时对象(重点!)
constData():获取 QByteArray 内部的字符指针
作用:返回 QByteArray 内部存储字节的首地址,类型是 const char*(C 风格字符串指针)。
注意:这个指针不拥有内存,只是 "指向" QByteArray 管理的内存 ------ 一旦 QByteArray 被销毁,指针就会指向已释放的内存(悬空指针)。
整数风格转换

函数:
(1)number(,) : 前者是空间名,后者是进制数,比如8进制
(2)ToInt( ,)第一个是判断是否转换成功的开关,第二个是转换的进制数
bool sFlag:是一个 "开关",用来存储转换的成功 / 失败状态。
&sFlag:是把开关的 "控制权" 交给 toInt 函数,让它能修改开关的状态
格式化风格转换

两种方法
第一种c语言风格:利用字符%s等含义搭配类函数QString::asprintf()使用
第二种方法QString自己的:先把const char *风格的转换成QString的
%1、%2 是 Qt 字符串占位符
同一个序号可以在字符串里多次出现,会被同一个 arg() 参数替换,比如:这里的%2
%1:表示第 1 个要替换的位置
%2:表示第 2 个要替换的位置
%1(数字)常见易错点:
序号不匹配
序号不用连续
函数
.arg() : 替换这些占位符
arg支持什么类型:全部都支持,自动转字符串,丢进去即可:
3.增删改查
3.1增加操作
append:尾插法(使用居多)
prepend:头插
insert( ,): 插入位置,插入内容
#include <QApplication>:能创建并运行一个 Qt 图形界面程序
#include <QCoreApplication>: 管理程序的事件循环(处理定时器、网络请求、异步任务等,只是没有界面相关的事件如鼠标点击)
3.2 是否为空的两个函数
isEMpty():指的内容是否为空
isNull(): QString().isNull() true
size() 字符个数
count() 总个数
contains(是否包含)
3.3 删除
尾删:
chop() :在原空间改变,不支持链式调用,从末尾开始删除,里面填多少,删多少个字符
比如:str=("11111") chop(2) 打印str=111
任意位置删除:
remove(1,4) :从头开始删除,一共删除4个(字符的位置)
全删除 clear()
3.4 替换
replace() :
QString x = "Say yes!";
QString y = "no";
x.replace(4, 3, y);
// x = "Say no!"
3.5 查找:
at front back
indexof(从头找第一个)
lastIndexOf(从尾找第一个)
QString x = "sticky question";
QString y = "sti";
x.indexOf(y); // returns 0
x.indexOf(y, 1); // returns 10
x.indexOf(y, 10); // returns 10
x.indexOf(y, 11); // returns -1
只返回第一次遇到的相同字符的索引
提取:left(从左提取多少个) right mid(截断)(都是返回新空间)
4.常用案例
lastIndexOf这种的返回类型是qsizetype(索引号)
left(pos): [0, pos) right(pos): 从右边数pos个符号提取
mid(pos+a.size() ,num) : 表示[ pos+a.size() , pos+num](从pos+a.size()开始截取num个字符,逗号后面可以不写)
5.容器
split返回的是容器类型

链式容器用c++的即可
map底层红黑树,键值对;
容器遍历方法:
索引方法
STL迭代器风格:
QList<QString> list = {"A", "B", "C", "D"};
for (auto i = list.begin(), end = list.end(); i != end; ++i)
*i = (*i).toLower();
// 1. 顺序容器
QList<int> arr1 = {2, 3, 4, 7, 8, 9};
for (auto &x : arr1) {
x += 1;
}
int x;
foreach(x, arr1) {
qDebug() << x;
}
// 2. 关联容器
QMap<QString, int> res2;
res2.insert("a1", 10);
res2["w1"] = 30;
res2["b1"] = 20;
for (auto start = res2.cbegin(), end = res2.cend(); start != end; ++start) {
qDebug() << start.key() << ": " << start.value();
}
QMap有序(红黑树,按照k值顺序)
QHash无序(哈希表)
关联容器另一种遍历方法
for (auto x: res2.keys()) {
qDebug() << x << ": " << res2[x];
}