在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容器。
myvector.cpp
#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中最常用的容器之一。
mylist.cpp
#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; }
在一个循环中,我们遍历容器并打印其元素。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是一个方便的容器,提供了一个字符串列表。它具有基于索引的快速访问,以及快速插入和删除。
mystringlist.cpp
#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风格的常量迭代器。
while (it.hasNext()) { out << it.next().trimmed() << endl; }
使用创建的迭代器,我们将列表的元素打印到终端。trimmed方法修剪字符串元素中的空格。
$ ./mystringlist coin book cup pencil clock bookmark
Qt5 QSet
Qt5 QSet是一个单值数学集合,提供快速查找。值存储在未指定的顺序中。
myset.cpp
#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集合的所有项目,除了颜色blue。
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是一个关联数组(字典),用于存储键值对。它提供了与一个键相关的值的快速查询。
myqmap.cpp
#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是一个Java风格的迭代器,用于QMap。它可用于遍历映射的元素。
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
自定义类排序
book.h
class Book {
public:
Book(QString, QString);
QString getAuthor() const;
QString getTitle() const;
private:
QString author;
QString title;
};
这是一个自定义类对象的排序示例,利用QList存储自定义的Book类对象。
book.h为Book类的头文件
book.cpp
#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.cpp为Book类的实现,构造函数用于初始化作者和书名,两个访问器方法返回对应的成员变量。
sortcustomclass.cpp
#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;
}
在这个例子中,我们创建了一些书对象,并使用 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