Qt库提供了基于通用模板的容器类, 这些类可用于存储指定类型的数据项,Qt中这些容器类的设计比STL容器更轻,更安全且更易于使用。容器类也都是隐式共的,它们是可重入的,并且已针对速度/低内存消耗和最小的内联代码扩展进行了优化,从而生成了较小的可执行文件。
容器类是基于模板的类,例如常用的QList<T>,T是一个具体的类,可以是int,float等简单类,也可以是QString、QDate类。T必须是一个可赋值的类型,即T必须提供一个默认构造函数,一个可复制的构造函数和一个赋值运算符。Qt的容器分为关联容器类和关联容器类, 顺序容器有:QList,QLinkedList,QVector,QStack和QQueue。
• QList是最适合使用的类型。它是作为数组列表实现的,提供了非常快的前置和追加操作。
• 如果需要一个链表,使用QLinkedList。
• 如果希望项目占据连续的内存位置,请使用QVector。
• QStack和QQueue是提供LIFO和FIFO语义的便捷类。
一,QT数据类型
QT基本数据类型定义在<QtGlobal>头文件中,QT基本数据类型
QT函数和宏定义,申明的宏使程序员能够向其应用程序添加编译器或平台特定的代码,而其他
宏则是用于较大操作的便捷宏, 比如Q_PROCESSOR_ARM,定义是否为ARM处理器编译应用
程序,Qt当前支持可选的ARM版本Q_PROCESSOR_ARM_V5,Q_PROCESSOR_ARM_V6和Q_PROCESSOR_ARM_V7。
返回值 函数 含义
T qAbs(const T &t) 绝对值函数
const T & qMax(const T &a, const T &b) 检索两个给定对象的最大值
const T & qMin(const T &a, const T &b) 检索两个给定对象的最小值
1, QString:
它存储16位Unicode字符,字符串和数值之间的转换:
QString str7 = "56.5";
qDebug()<<str7.toInt();
qDebug()<<str7.toDouble();
qDebug()<<str7.toFloat();
qDebug()<<str7.toLong();
qDebug()<<QString::number(53);
qDebug()<<QString::number(4.4156);
qDebug()<<QString::number(4.4156,'f',2);
QString str8 = "F0F0";
bool OK;
int val = str8.toInt(&OK,16);
qDebug()<<val;
qDebug()<<QString::number(val,2);
qDebug()<<QString::number(val,8);
qDebug()<<QString::number(val,10);
qDebug()<<QString::number(val,16);
8位字符串和Unicode字符串之间转换,以QByteArray的形式返回字符串
qDebug()<<str8.toLocal8Bit();
qDebug()<<str8.toLatin1();
qDebug()<<str8.toUtf8();
toLatin1() 返回 Latin-1(ISO 8859-1)编码的8位字符串。
• toUtf8() 返回UTF-8编码的8位字符串。UTF-8是US-ASCII(ANSI X3.4-1986)的超集,它
通过多字节序列支持整个 Unicode 字符集。
• toLocal8Bit() 使用系统的本地编码返回 8 位字符串。
QString 也提供了 fromLatin1(),fromUtf8() 和 fromLocal8Bit() 对应的转换函数。
字符串的拆分和拼接,除了前面提到的append(),prepend(),insert(),replace()和remove(),indexOf()或lastIndexOf() 以及trimped()和simplified()。
2, QStringList
QStringList继承自QList<QString>,提供字符串列表,QList的所有功能也适用于QStringList。例如
可以使用 isEmpty() 测试列表是否为空,并且可以调用诸如append(),prepend(),insert(),replace(),removeAll(),removeAt(),removeFirst(),removeLast()和removeOne()之类的函数来修QStringList。QStringList提供了一些便利功能,这些功能使处理字符串列表更加容易:通过insert() append()或者重载的operator+=() 和 operator «()将字符串添加到列表中
QStringList fonts = { "Arial", "Helvetica", "Times" };
fonts << "Courier" << "Verdana";
fonts += "chinese";
for (int i = 0; i < fonts.size(); ++i)
{
qDebug()<< fonts.at(i).toLocal8Bit().constData();
}
QStringListIterator javaStyleIterator(fonts);
while (javaStyleIterator.hasNext())
{
qDebug() << javaStyleIterator.next().toLocal8Bit().constData();
}
QStringList::const_iterator constIterator;
for(constIterator=fonts.constBegin(); constIterator!=fonts.constEnd();,++constIterator)
{
qDebug() << (*constIterator).toLocal8Bit().constData();
}
3,QByteArray
QByteArray用于存储原始字节(包括’0’和传统的以’0’结尾的 8 位字符串)。使用QByteArray比使用const char*更为方便。QByteArray在主要以下两种情况中使用:需要存储原始二进制数据时和在内存保护至关重要。QByteArray可以包含“0”, rize()函数总会计算”0”,但是date()和constData()返回结果总是以”0”作为结束标志:
qDebug()<<byte.right(2);
qDebug()<<byte.left(2);
qDebug()<<byte.mid(2,2);
QByteArray byte1("ca\0r\0t");
qDebug()<<byte1.size(); // Returns 2.
qDebug()<<byte1.data();
qDebug()<<byte1.constData(); // Returns "ca" with␣
QByteArray byte2("ca\0r\0t", 3);
qDebug()<<byte2.size(); // Returns 3.
qDebug()<<byte2.constData(); // Returns "ca\0" with,→terminating \0.
QByteArray byte3("ca\0r\0t", 4);
qDebug()<<byte3.size(); // Returns 4.
qDebug()<<byte3.constData(); // Returns "ca\0r" with␣terminating \0.
for(int i=0; i<byte3.size();i++)
{
qDebug()<<byte3.at(i);
}
const char cart[] = {'c', 'a', '\0', 'r', '\0', 't'};
QByteArray byte4(QByteArray::fromRawData(cart, 6));
qDebug()<<byte4.size(); // Returns 6.
qDebug()<<byte4.constData(); // Returns "ca\0r\0t" without␣terminating \0.
resize()可以重新设置数组的大小,并按字节数重新初始化数据字节。QByteArray使用基于0的
索引,就像C++数组一样,可以使用operator[]访问特定索引位置的字节,如果只读,我们也可以使用at()访问指定的字节,left()、right()或 mid()则可以一次读取多个字节:
byte.resize(5);
byte[0] = 0x3c;
byte[1] = 0xb8;
byte[2] = 0x64;
byte[3] = 0x18;
byte[4] = 0xca;
qDebug()<<byte;
qDebug()<<byte[3];
qDebug()<<byte[4];
for (int i = 0; i < byte.size();i++)
{
qDebug()<<byte.at(i);
}
qDebug()<<byte.right(2);
qDebug()<<byte.left(2);
qDebug()<<byte.mid(2,2);
QByteArray提供用于修改字节数据的基本功能:追加append(),前置添加prepend(),插入
insert(),替代replace()和移除remove()。indexOf()或lastIndexOf()提供查找QByteArray中所有出现的特定字符或子字符串,返回字符或子字符串的索引位置(如果找到的话)。contains()用于检查 QByteArray是否包含特定字符或子字符串,count()则可以用来统计特定字符或子字符串在字节数组中出现的次数。
QByteArray byte5("and");
qDebug()<<byte5;
byte5.prepend("rock ");
qDebug()<<byte5;
byte5.append(" roll");
qDebug()<<byte5;
byte5.replace(5, 3, "&");
qDebug()<<byte5;
QByteArray byte6("We must be <b>bold</b>, very <b>bold</b>");
int j = 0;
while ((j = byte6.indexOf("<b>", j)) != -1)
{
qDebug() << "Found <b> tag at index position " << j;
++j;
}
if(byte6.contains("b"))
{
qDebug()<<byte6.count("b");
}
4, QBitArray
QBitArray是一个数组,访问单个位并提供在整个位数组上工作的运算符(AND,OR,XOR和NOT)。
使用testBit()和setBit()访QBitArray中的位比使用operator[]效率更高:
bit.setBit(0, false);
bit.setBit(1, true);
bit.setBit(2, false);
qDebug()<<bit;
QBitArray区分数组null和empty;分别通过isNull()和isEmpty()来判断
isNull()如果此位数组为null,则返回true;否则返回false;
isEmpty()此位数组的大小是否为0,是返回true;否则返回false
qDebug()<<QBitArray().isNull();
qDebug()<<QBitArray().isEmpty();
qDebug()<<QBitArray(3).isNull();
qDebug()<<QBitArray(3).isEmpty();
QBitArray支持位运算
QBitArray bit_x(5);
bit_x.setBit(3, true);// x: [ 0, 0, 0, 1, 0 ]
QBitArray bit_y(5);
bit_y.setBit(4, true);// y: [ 0, 0, 0, 0, 1 ]
bit_x |= bit_y;// x: [ 0, 0, 0, 1, 1 ]
qDebug()<<bit_x<<bit_y;
bit_x &= bit_y;// x: [ 0, 0, 0, 0, 1 ]
qDebug()<<bit_x<<bit_y;
二,连续容器和关联容器
1,QVector:头文件包含#include<QVector>
是对所有数组的封装,例如想创建一个数组,可以写成QVector array(7),也可以写成QVector array,就是说数组大小可以预先定义也可以先不定义。不论是否有定义,都可以使用array.count()或者array.size()获取到数组元素的个数。
QVector使用的是连续的内存空间,针对不改变的对象,即只要求查询,不做插入删除等操作效率高,但是由于自身结构的原因,插入删除甚至包括追加等操作的效率会比QLIst低。
添加元素办法1
QVector<QString> strArray;
strArray.append("AAA");
添加元素办法2
QVector<QString> strArray;
strArray<<"BBB"; //可以这样
strArray<<"MyName"<<"is"<<"LEO";
插入
strArray.insert(1,"YYY");
删除
strArray.remove(1); //删除第一个元素,从0开始
strArray.remove(1,3); //从1开始,删除3个元素
strArray.pop_back(); // 删除末尾元素
strArray.pop_front(); // 删除开始位置元素
替换
strArray.replace(1,"LED");
末尾追加
append()
遍历办法1
QVector<double> vect(2);
vect[0] = 1.0;
vect[1] = 2.0;
for (int i = 0; i < vect.count(); ++i)
{
qDebug() << vect[i];
}
遍历办法2
QVector vect(2);
for(auto a = vect.begin(); a != vect.end(); a++)
{
qDebug() << *a;
}
遍历办法3:迭代器
QVector<QString>::iterator iter;
for (iter=strArray.begin();iter!=strArray.end();iter++)
{
qDebug() << *iter << "\0";
}
2,QList
QList是基于数组+链表,即各个节点的 指针不是通过Next来指向,而是通过将各节点的指针存放在一个数组中,遍历通过找到数组中的指向该节点的指针,再通过指针将节点找到. 相比QVector, QList采用的是分散存储,查找效率跟QVector差不多,也可用于插入、删除等操作,所以一般推荐如果不是强制要求使用QVector,优先选择QList。
添加
QList<QString> List;
List << "AAA" << "BBB";
List.append("CCC"); //尾部添加
List.push_back("CCC");
List.prepend("DDD"); //头部添加
List.push_front("DDD");
删除方式1:从列表删除
QString str = List.takeAt(2); //从列表中删除第3个元素,并获取它
删除方式2:从列表删除
List.removeAt(2);//从列表中删除第3个元素
删除方式3:根据内容删除
QList<QString> list;
list << "sun" << "cloud" << "sun" << "rain";
list.removeOne("sun");
改变位置
list.swap(1,3);//交换位置1和位置3的元素
list.move(1,4);//把第一个元素移到第四个元素,其他元素顺移
修改
QList<QString> list;
list << "AAA" << "BBB" << "CCC";
list.replace(1, "DDD");//参数1 元素下标, 参数2 修改的结果值
查找方式1
int index = list.indexOf("mm");//返回该元素的下标值
查找方式2
bool isCon = list.contains("23");//列表是否有某元素 成功返回true 否则false
查找方式3
index = list.count();//列表总元素 同list.length();
index = list.count("AAA");//列表中有几个这样的元素
遍历访问方式1:
for(int i = 0; i < list.size(); ++i)
{
//at()操作比操作符[]更快,因为它不需要深度复制
qDebug() << list[i] << list.at(i) << list.value(i) ;
}
遍历访问方式2:迭代器
QList<QString>::iterator it;
for(it=list.begin(); it!=list.end();++it)
{
if((*it)== "00")
{
it = list.erase(it,it+2);//删除从起始位置到结束位置的元素
}
qDebug() << "it" << (*it);
}
3,QLinkedList
基于索引的API比QLinkedList的基于迭代器的API更方便,并且由于其将项存储在内存中的方式,它通常比QVector更快. 但是,如果您需要一个真正的链表,并且要用来保存大量数据和保证在列表中间不断插入时间,迭代器可以迭代项而不是索引,请使用QLinkedList。
添加方式1
QLinkedList<QString> Listl;
List << "AAA" << "BBB" << "CCC";
添加方式2
QLinkedList<QString> List;
list.append("aaa"); //链表尾部插入
list.push_back("aaa"); //链表尾部插入
list.push_front("5");//链表表头插入
删除
QLinkedList<QString> List;
list << "sun" << "cloud" << "sun" << "rain";
list.removeOne("sun");
list.removeFirst();
list.removeLast();
list.clear();
遍历
QLinkedList<QString> list;
list<<"1"<<"2"<<"3"<<"4";
// foreach正序:
QString str;
foreach (str, list)
{
qDebug() << str;
}
// 迭代器正序
QLinkedList<QString>::iterator it;
for(it = list.begin(); it != list.end(); ++it)
{
qDebug() << *it;
}
// 迭代器倒序
QLinkedList<QString>::const_iterator it = list.constEnd();
while (it != list.constBegin())
{
--it;
qDebug()<<*it;
}
4,QByteArray
要存储纯二进制数据(raw binary data)(原始数据)或8-bit编码文本字符串就用QByteArray
访问:QByteArray的访问方式有四种:[]、data[]和at()、constData[]。其中[]和data[]为可读可写;at()和constData[]为只读,因此访问用这两种速度较快。
QByteArray ba;
ba.resize(3);
ba[0] = 0x30;
ba[1] = 0x31;
ba[2] = 0x32;
qDebug() << ba.toHex(); //return “303132”
查找
QByteArray x("sticky question");
QByteArray y("sti");
x.indexOf(y); //returns 0
数据转换
QByteArray ba;
int n = 63;
ba.setNum(n); // ba == “63”
ba.setNum(n, 16); // ba == “3f”
left、right、mid操作
//left
QByteArray x("Pineapple");
QByteArray y = x.left(4);
// y == "Pine"
//right
QByteArray x("Pineapple");
QByteArray y = x.right(5);
// y == "apple"
//mid
QByteArray x("Five pineapples");
QByteArray y = x.mid(5, 4); // y == "pine"
QByteArray z = x.mid(5); // z == "pineapples"
5,QSet
基于哈希表实现的一种单值的数学集合的快速查找容器,使用方式与QList相同,但其内元素不会有重复。
插入
struct node
{
int cx;
QString str;
};
QSet<node> ss;
for(i=0,j=100;i<101;i++,j--)
{
temp.cx = i;
temp.cy = j;
ss.insert(temp);
}
遍历
QSet<node>::iterator iter;
for(iter=ss.begin();iter!=ss.end();++iter)
{
qDebug() << iter->cx << " " << iter->cy;
}
应用举例
// 创建一个字符串类型的集合(QSet)对象,名为 set
QSet<QString> set;
// 向集合中插入字符串"one" 、"three"、"seven"
set.insert("one");
set.insert("three");
set.insert("seven");
// 使用流操作符连续插入字符串"twelve"、"fifteen"、"nineteen" 到集合中
set << "twelve" << "fifteen" << "nineteen";
// 判断集合中是否包含字符串"fifteen",如果包含则输出"set contains fifteen"
if (set.contains("fifteen"))
qDebug()<<"set contains fifteen";
// 使用 foreach 循环遍历集合中的字符串,并输出其值
foreach (const QString &value, set)
qDebug() << value;
6,QStack
QStack是一种基于栈(Stack)的高级数据结构,QStack容器是一种后进先出(LIFO)的数据结构,即最后一个进入堆栈的元素将最先被移除。堆栈是后进先出(LIFO)结构,使用 push()将项目添加到堆栈的顶部,并使用pop()从顶部检索项目。在 top()函数可以访问到的最上方项目而不删除。
// 创建一个整数类型的栈(QStack)对象,名为stack
QStack<int> stack;
// 使用 push() 压入元素
stack.push(1);
stack.push(2);
stack.push(3);
// 使用 top() 查看栈顶元素
qDebug() << "Top element:" << stack.top();
// 使用 size() 查看堆栈大小
qDebug() << "Stack size:" << stack.size();
// 使用 pop() 移除并返回栈顶元素
int poppedValue = stack.pop();
qDebug() << "Popped value:" << poppedValue;
// 使用 isEmpty() 检查堆栈是否为空
qDebug() << "堆栈是否空的:" << (stack.isEmpty() ? "Yes" : "No");
// 使用 operator<< 压入元素
stack << 4 << 5;
// 当栈不为空时执行循环,输出并弹出栈顶的元素
while (!stack.isEmpty())
qDebug() << stack.pop();
qDebug() << "堆栈是否空的:" << (stack.isEmpty() ? "Yes" : "No");
7,QQueue
QQueue类是提供队列的通用容器,队列是先进先出(FIFO)结构。使用enqueue()将项目添加到队列的尾部,并使用dequeue()从项目头检索项目,head()函数提供了访问头项目而不删除数据。QQueue继承自QList,因此可以方便地利用QList的功能实现队列的基本操作。QQueue提供 enqueue(),dequeue()和 head()三个便利功能,实现fifo定义
//创建一个空的 int 型 QQueue 对象,名为 queue
QQueue<int> queue;
//入队
queue.enqueue(1);
queue.enqueue(2);
queue.enqueue(3);
//获取队列大小
qDebug() << "队列大小:" << queue.size();
//检查队列是否为空
qDebug() << "队列是否为空:" << queue.isEmpty();
//查看队列的头部元素
qDebug() << "队列的头部元素:" << queue.head();
/出队元素
int firstElement = queue.dequeue();
qDebug() << "出队元素:" << firstElement;
//获取队列中的第一个和最后一个元素
qDebug() << "First element:" << queue.first();
qDebug() << "Last element:" << queue.last();
//检查队列是否包含特定值
qDebug() << "检查队列是否包含特定值 3:" << queue.contains(3);
//出队所有元素
while (!queue.isEmpty())
qDebug() << queue.dequeue();
8,QVariant
QVariant类是Qt的共用体union数据类型,不仅能保存很多Qt类型的值,包括QColor,QBrush,
QFont,QRect,QString及QSize等等,而且能存放Qt的容器类型值. 常用于存储不同的数据类型,可以在接口返回值中广泛使用。
定义一个int类型的QVariant
QVariant vNum(100);
qDebug() << vNum.toInt();
定义一个float类型的QVariant
QVariant vPI(3.14);
qDebug() << vPI.toFloat();
定义一个QString类型的QVariant
QVariant vStr("Hello!");
qDebug() << vStr.toString();
定义一个bool类型的QVariant
QVariant vBool(false);
qDebug() << vBool.toBool();
定义一个QColor类型的
QVariantQColor color = QColor(Qt::yellow);
QVariant vColor(color);
qDebug() << vColor.type();
qDebug() << vColor.value<QColor>();
9,QMultiMap
QMultiMap继承自QMap并对其功能进行了扩展,使其能够存储多个值,多值映射是一种允许使
用同一键的多个值的映射。
// 声明三个 QMultiMap 类型的变量,QMultiMap 是一种可以存储键值对的容器,并且可以存储重
复的键。
QMultiMap<QString, int> map1, map2, map3;
map1.insert("plenty", 100); // 在 map1 中插入键为"plenty",值为 100 的元素
map1.insert("plenty", 2000); // 在 map1 中再次插入键为"plenty",值为 2000 的元
素,这不会覆盖之前的元素,而是在相同键下插入新的元素
qDebug()<<map1.size();
map2.insert("plenty", 5000); // 在 map2 中插入键为"plenty",值为 5000 的元素。
qDebug()<<map2.size();
// 使用 QMultiMap 的 operator+ 将 map1 和 map2 合并,结果存储在 map3 中
// 如果两个 map 中存在相同的键,那么在 map3 中该键对应的值将是两个 map 中该键对应的所有
值的集合
map3 = map1 + map2;
qDebug()<<map3.size();
// 获取在 map3 中键为"plenty" 的所有值,并将这些值存储到列表中
// 然后遍历 valueslist,并输出其中的每个值
QList<int> valueslist = map3.values("plenty");
for (int i = 0; i< valueslist.size(); ++i)
qDebug() << valueslist.at(i);
10,QMap
基于红黑树算法的一套字典,它通过(Key, value)存储一对值,并通过Key可以查找与之关联的value的值,在QMap中,项总是按键排序。
插入:可以用运算符[ ]插入一对 (key,value) 到QMap对象中:
QMap<QString, int> map;
map["one"] = 1;
map["three"] = 3;
map["seven"] = 7;
使用函数insert()插入
QMap<QString, int> map;
map.insert("twelve", 12);
查询:获取值
int num1 = map["thirteen"];
int num2 = map.value("thirteen");
查看QMap对象中是否包含某一项:
int timeout;
if (map.contains("TIMEOUT"))
{
timeout = map.value("TIMEOUT");
}
遍历:查看键值
QMap<QString, int> map;
map["one"] = 1;
map["three"] = 3;
QMapIterator<QString, int> i(map);
while (i.hasNext())
{
i.next();
cout << i.key() << ": " << i.value() << endl;
}
遍历:只查看值
QMap<QString, int> map;
foreach (int value, map)
cout << value << endl;
11,QHash
和QMap区别是,QHash中的键值对不会进行自动排序,而是根据Hash值存储。QHash中每个键只允许一个值,它提供比QMap更快的查找,但所需空间更大。在QHash中,键值是任意排序,QMap默认按照键值升序排序。
插入
QHash<int,QString> qhash;
//方式一
qhash[1] = "1";
qhash[2] = "2";
qhash[3] = "3";
//方式二
qhash.insert(4, “4”);
获取值
//方式一
QString str1=qhash.value(1);//str1="1";
//方式二
QString str2=qhash[2];//str1="2";
查找
QString str;
if(qhash.contains(1))
{
str=qhash.value(1);
}
遍历
QHash<int,QString>::const_iterator it = qhash.constBegin();
while (it != qhash.constEnd())
{
qDebug() << it.key() << ": " << it.value();
++i;
if(it.value() == "aaa")
{
qhash.erase(it);//删除
}
}
删除
qhash.erase(it);//在迭代器中使用
qhash.remove(key);
三,迭代器