Qt5 中的容器
最后修改于 2023 年 10 月 18 日
在 Qt5 教程的这一部分,我们将讨论 Qt5 中的容器。以下容器被提及:QVector
, QList
, QStringList
, QSet
和 QMap
。
容器是通用类,用于将给定类型的项目存储在内存中。C++ 有标准模板库 (STL),它有自己的容器。在 Qt 中,我们可以使用 Qt 容器或 STL 容器。
有两种容器:顺序容器和关联容器。顺序容器将项目一个接一个地存储,而关联容器存储键值对。QList
、QVector
、QLinkedList
属于顺序容器;QMap
和 QHash
是关联容器的例子。
由于在本章中我们创建命令行程序,我们不需要 Qt GUI 模块。我们可以将 QT -= gui
声明添加到项目文件中。
Qt5 QVector
QVector
是一个提供动态数组的模板类。它将其项目存储在相邻的内存位置,并提供基于索引的快速访问。对于大型向量,插入操作较慢,建议使用 QList
容器。
#include <QVector> #include <QTextStream> int main(void) { QTextStream out(stdout); QVector<int> vals = {1, 2, 3, 4, 5}; out << "The size of the vector is: " << vals.size() << endl; out << "The first item is: " << vals.first() << endl; out << "The last item is: " << vals.last() << endl; vals.append(6); vals.prepend(0); out << "Elements: "; for (int val : vals) { out << val << " "; } out << endl; return 0; }
该示例使用整数向量。
QVector<int> vals = {1, 2, 3, 4, 5};
创建了一个整数向量。
out << "The size of the vector is: " << vals.size() << endl;
size
方法给出向量的大小——向量中的项目数。
out << "The first item is: " << vals.first() << endl;
第一个项目使用 first
方法检索。
out << "The last item is: " << vals.last() << endl;
向量的最后一个项目使用 last
方法找到。
vals.append(6);
append
方法将值插入到向量的末尾。
vals.prepend(0);
prepend
方法将值插入到向量的开头。
for (int val : vals) { out << val << " "; }
我们在 for 循环中遍历向量并打印其内容。
$ ./myvector The size of the vector is: 5 The first item is: 1 The last item is: 5 Elements: 0 1 2 3 4 5 6
Qt5 QList
QList
是用于创建元素列表的容器。它类似于 QVector
。它存储一个值列表,并提供基于索引的快速访问以及快速插入和删除。它是 Qt 中最常用的容器之一。
#include <QTextStream> #include <QList> #include <algorithm> int main(void) { QTextStream out(stdout); QList<QString> authors = {"Balzac", "Tolstoy", "Gulbranssen", "London"}; for (int i=0; i < authors.size(); ++i) { out << authors.at(i) << endl; } authors << "Galsworthy" << "Sienkiewicz"; out << "***********************" << endl; std::sort(authors.begin(), authors.end()); out << "Sorted:" << endl; for (QString author : authors) { out << author << endl; } return 0; }
该示例展示了 QList
容器。
QList<QString> authors = {"Balzac", "Tolstoy", "Gulbranssen", "London"};
创建了一个 QList
容器。它存储作家的名字。
for (int i=0; i < authors.size(); ++i) { out << authors.at(i) << endl; }
在 for 循环中,我们遍历容器并打印其元素。at
方法返回给定索引处的项目。
authors << "Galsworthy" << "Sienkiewicz";
<< 运算符用于将两个新项目插入到列表中。
std::sort(authors.begin(), authors.end());
std::sort
方法按升序对列表进行排序。
out << "Sorted:" << endl; for (QString author : authors) { out << author << endl; }
现在我们打印排序后的列表。
$ ./mylist Balzac Tolstoy Gulbranssen London *********************** Sorted: Balzac Galsworthy Gulbranssen London Sienkiewicz Tolstoy
QStringList
QStringList
是一个方便的容器,提供字符串列表。它具有基于索引的快速访问以及快速插入和删除。
#include <QTextStream> #include <QList> int main(void) { QTextStream out(stdout); QString string = "coin, book, cup, pencil, clock, bookmark"; QStringList items = string.split(","); QStringListIterator it(items); while (it.hasNext()) { out << it.next().trimmed() << endl; } return 0; }
在本例中,我们从一个字符串创建一个字符串列表,并将元素打印到控制台中。
QString string = "coin, book, cup, pencil, clock, bookmark"; QStringList items = string.split(",");
QString
的 split
方法根据提供的分隔符将字符串分割成子字符串。子字符串以列表形式返回。
QStringListIterator it(items);
QStringListIterator
为 QStringList
提供 Java 风格的 const 迭代器。
while (it.hasNext()) { out << it.next().trimmed() << endl; }
使用创建的迭代器,我们将列表的元素打印到终端。trimmed
方法修剪字符串元素中的空格。
$ ./mystringlist coin book cup pencil clock bookmark
Qt5 QSet
QSet
提供具有快速查找的单值数学集合。这些值以未指定的顺序存储。
#include <QSet> #include <QList> #include <QTextStream> #include <algorithm> int main(void) { QTextStream out(stdout); QSet<QString> cols1 = {"yellow", "red", "blue"}; QSet<QString> cols2 = {"blue", "pink", "orange"}; out << "There are " << cols1.size() << " values in the set" << endl; cols1.insert("brown"); out << "There are " << cols1.size() << " values in the set" << endl; cols1.unite(cols2); out << "There are " << cols1.size() << " values in the set" << endl; for (QString val : cols1) { out << val << endl; } QList<QString> lcols = cols1.values(); std::sort(lcols.begin(), lcols.end()); out << "*********************" << endl; out << "Sorted:" << endl; for (QString val : lcols) { out << val << endl; } return 0; }
QSet
用于在本例中存储颜色。指定一个颜色值多次是没有意义的。
QSet<QString> cols1 = {"yellow", "red", "blue"}; QSet<QString> cols2 = {"blue", "pink", "orange"};
我们有两个颜色值集合。蓝色位于两个集合中。
out << "There are " << cols1.size() << " values in the set" << endl;
size
方法返回集合的大小。
cols1.insert("brown");
我们使用 insert
方法向集合添加一个新值。
cols1.unite(cols2);
unite
方法执行两个集合的并集。cols1
集合将包含来自 cols2
集合的所有未存在的项目;在本例中,除了蓝色之外的所有颜色。
for (QString val : cols1) { out << val << endl; }
通过 for 循环,我们打印 cols1
集合中的所有项目。
QList<QString> lcols = cols1.values(); std::sort(lcols.begin(), lcols.end());
不支持集合的排序。我们可以从集合中创建一个列表并对其进行排序。values
方法返回一个包含集合中元素的新的 QList
。QList
中元素的顺序是未定义的。
$ ./myset There are 3 values in the set There are 4 values in the set There are 6 values in the set pink orange brown blue yellow red ********************* Sorted: blue brown orange pink red yellow
Qt5 QMap
QMap
是一个关联数组(字典),它存储键值对。它提供了与键关联的值的快速查找。
#include <QTextStream> #include <QMap> int main(void) { QTextStream out(stdout); QMap<QString, int> items = { {"coins", 5}, {"books", 3} }; items.insert("bottles", 7); QList<int> values = items.values(); out << "Values:" << endl; for (int val : values) { out << val << endl; } QList<QString> keys = items.keys(); out << "Keys:" << endl; for (QString key : keys) { out << key << endl; } QMapIterator<QString, int> it(items); out << "Pairs:" << endl; while (it.hasNext()) { it.next(); out << it.key() << ": " << it.value() << endl; } return 0; }
在本例中,我们有一个字典,我们将字符串键映射到整数值。
QMap<QString, int> items = { {"coins", 5}, {"books", 3} };
创建了一个 QMap
。它有两个对。
items.insert("bottles", 7);
使用 insert
方法插入一个新对。
QList<int> values = items.values(); out << "Values:" << endl; for (int val : values) { out << val << endl; }
我们获取字典的所有值并将它们打印到控制台。values
方法返回一个地图值列表。
QList<QString> keys = items.keys(); out << "Keys:" << endl; for (QString key : keys) { out << key << endl; }
同样,我们打印字典的所有键。keys
方法返回一个包含字典中所有键的列表。
QMapIterator<QString, int> it(items);
QMapIterator
是 QMap
的 Java 风格迭代器。它可以用于迭代地图的元素。
while (it.hasNext()) { it.next(); out << it.key() << ": " << it.value() << endl; }
在迭代器的帮助下,我们遍历地图的所有元素。key
方法返回当前键,而 value
方法返回当前值。
$ ./myqmap Values: 3 7 5 Keys: books bottles coins Pairs: books: 3 bottles: 7 coins: 5
自定义类排序
在下面的例子中,我们将对自定义类的对象进行排序 QList
。
class Book { public: Book(QString, QString); QString getAuthor() const; QString getTitle() const; private: QString author; QString title; };
这是我们自定义 Book
类的头文件。
#include <QString> #include "book.h" Book::Book(QString auth, QString tit) { author = auth; title = tit; } QString Book::getAuthor() const { return author; } QString Book::getTitle() const { return title; }
这是 Book
类的实现;我们有两个访问器方法。
#include <QTextStream> #include <QList> #include <algorithm> #include "book.h" bool compareByTitle(const Book &b1, const Book &b2) { return b1.getTitle() < b2.getTitle(); } int main(void) { QTextStream out(stdout); QList<Book> books = { Book("Jack London", "The Call of the Wild"), Book("Honoré de Balzac", "Father Goriot"), Book("Leo Tolstoy", "War and Peace"), Book("Gustave Flaubert", "Sentimental education"), Book("Guy de Maupassant", "Une vie"), Book("William Shakespeare", "Hamlet") }; std::sort(books.begin(), books.end(), compareByTitle); for (Book book : books) { out << book.getAuthor() << ": " << book.getTitle() << endl; } return 0; }
在本例中,我们创建了几个 book 对象,并使用 std::sort
算法对它们进行排序。
bool compareByTitle(const Book &b1, const Book &b2) { return b1.getTitle() < b2.getTitle(); }
compareByTitle
是排序算法使用的比较函数。
std::sort(books.begin(), books.end(), compareByTitle);
std::sort
算法按书的标题对列表中的书进行排序。
$ ./sortcustomclass Honoré de Balzac: Father Goriot William Shakespeare: Hamlet Gustave Flaubert: Sentimental education Jack London: The Call of the Wild Guy de Maupassant: Une vie Leo Tolstoy: War and Peace
在本章中,我们使用了 Qt 的容器。