首页 » 网站推广 » phpprintr数组技巧_c 运用反向迭代器适配器向后迭代

phpprintr数组技巧_c 运用反向迭代器适配器向后迭代

duote123 2024-11-05 0

扫一扫用手机浏览

文章目录 [+]

反向迭代器适配器是一个抽象,它反转了迭代器类的顺序。
它须要一个双向迭代器。

如何做到这一点…

大多数双向容器在 STL 中都包含了一个反向迭代器适配器。
其他容器,如原始 C 数组,没有。
让我们来看看一些例子:

phpprintr数组技巧_c 运用反向迭代器适配器向后迭代

让我们从本章中一贯利用的 printc() 函数开始:

phpprintr数组技巧_c 运用反向迭代器适配器向后迭代
(图片来自网络侵删)

void printc(const auto & c, const string_view s = "") { if(s.size()) cout << format("{}: ", s); for(auto e : c) cout << format("{} ", e); cout << '\n';}

这个利用基于范围的 for 循环来打印容器的元素。

基于范围的 for 循环纵然与没有迭代器类的原始 C 数组一起事情也可以。
以是,我们的 printc() 函数已经可以与 C 数组一起事情:

int main() { int array[]{1, 2, 3, 4, 5}; printc(array, "c-array");}

我们得到这个输出:

c-array: 1 2 3 4 5

我们可以利用 begin() 和 end() 迭代器适配器为 C 数组创建正常的前向迭代器:

auto it = std::begin(array);auto end_it = std::end(array);while (it != end_it) { cout << format("{} ", it++);}

for 循环的输出:

1 2 3 4 5

或者我们可以利用 rbegin() 和 rend() 反向迭代器适配器为 C 数组创建反向迭代器:

auto it = std::rbegin(array);auto end_it = std::rend(array);while (it != end_it) { cout << format("{} ", it++);}

现在我们的输出是相反的:

5 4 3 2 1

我们乃至可以创建一个修正版的 printc(),以相反的办法打印:

void printr(const auto & c, const string_view s = "") { if(s.size()) cout << format("{}: ", s); auto rbegin = std::rbegin(c); auto rend = std::rend(c); for(auto it = rbegin; it != rend; ++it) { cout << format("{} ", it); } cout << '\n';}

当我们用 C 数组调用它:

printr(array, "rev c-array");

我们得到这个输出:

rev c-array: 5 4 3 2 1

当然,这与任何双向 STL 容器一样有效:

vector<int> v{1, 2, 3, 4, 5};printc(v, "vector");printr(v, "rev vector");

输出:

vector: 1 2 3 4 5rev vector: 5 4 3 2 1

它是如何事情的…

一个正常的迭代器类有一个指向第一个元素的 begin() 迭代器,和一个指向末了一个元素之后的 end() 迭代器:

前向迭代器

你通过利用 ++ 运算符递增 begin() 迭代器,直到它达到 end() 迭代器的值来迭代容器。

一个反向迭代器适配器拦截迭代器接口并将其反转,使得 begin() 迭代器指向末了一个元素,end() 迭代器指向第一个元素之前。
++ 和 -- 运算符也被反转:

反向迭代器适配器

在反转的迭代器中,++ 运算符递减,-- 运算符递增。

值得把稳的是,大多数双向 STL 容器已经包含了一个通过成员函数 rbegin() 和 rend() 访问的反向迭代器适配器:

vector<int> v;it = v.rbegin();it_end = v.rend();

这些迭代器将以相反的方向操作,适宜许多目的。

利用哨兵迭代未知长度的工具

一些工具没有特定的长度。
要理解它们的长度,你须要迭代它们所有的元素。
例如,在本章的其他地方,我们已经看到了一个没有特定长度的天生器。
一个更常见的例子是 C 字符串。

C 字符串是一个以空字符 '\0' 终止的原始 C 字符数组。

带有其空终止符的 C 字符串

我们一贯在利用 C 字符串,纵然我们没故意识到。
任何 C/C++ 中的字面字符串都是 C 字符串:

std::string s = "string";

这里,STL 字符串 s 用字面字符串初始化。
字面字符串是 C 字符串。
如果我们以十六进制查看各个字符,我们将看到空终止符:

for (char c : "string") { std::cout << format("{:02x} ", c);}

单词 "string" 有六个字母。
我们的循环输出显示数组中有七个元素:

73 74 72 69 6e 67 00

第七个元素是空终止符。

循环看到的是字符的原始 C 数组,有七个值。
它是一个字符串是一个抽象,对循环不可见。
如果我们想让循环将其视为字符串,我们将须要一个迭代器和一个哨兵。

哨兵是一个工具,它发出迭代器的不愿定长度的结束旗子暗记。
当迭代器到达数据的末端时,哨兵将与迭代器相等。

为了看看这个是如何事情的,让我们为 C 字符串构建一个迭代器!

如何做到这一点…

要利用 C 字符串的哨兵,我们须要构建一个自定义迭代器。
它不须要繁芜,只须要基本功能,以便与基于范围的 for 循环一起利用。

我们将从几个方便的定义开始:

using sentinel_t = const char;constexpr sentinel_t nullchar = '\0';

对付 sentinel_t 的 using 别名是 const char。
我们将在我们的类中利用这个作为哨兵。

我们还定义了空字符终止符的常量 nullchar。

现在我们可以定义我们的迭代器类型:

class cstr_it { const char s{};public: explicit cstr_it(const char str) : s{str} {} char operator() const { return s; } cstr_it& operator++() { ++s; return this; } bool operator!=(sentinel_t) const { return s != nullptr && s != nullchar; } cstr_it begin() const { return this; } sentinel_t end() const { return nullchar; }};

这很简短大略。
这是基于范围的 for 循环所需的最小必要性。
把稳 end() 函数返回 nullchar,operator!=() 重载与 nullchar 进行比较。
这便是我们为哨兵所需的全部。

现在我们可以定义一个利用哨兵打印我们的 C 字符串的函数:

void print_cstr(const char s) { cout << format("{}: ", s); for (char c : cstr_it(s)) { std::cout << format("{:02x} ", c); } std::cout << '\n';}

在这个函数中,我们首先打印字符串。
然后我们利用 format() 函数将每个字符作为十六进制值打印。

现在我们可以从我们的 main() 函数调用 print_cstr():

int main() { const char carray[]{"array"}; print_cstr(carray); const char cstr{"c-string"}; print_cstr(cstr);}

输出看起来像这样:

array: 61 72 72 61 79c-string: 63 2d 73 74 72 69 6e 67

把稳没有多余的字符,没有空终止符。
这是由于我们的哨兵见告 for 循环在看到 nullchar 时停滞。

它是如何事情的…

迭代器类的哨兵部分非常大略。
我们可以通过在 end() 函数中返回它来轻松利用空终止符作为哨兵值:

sentinel_t end() const { return nullchar; }

然后,不相等比较运算符可以测试它:

bool operator!=(sentinel_t) const { return s != nullptr && s != nullchar;}

把稳参数只是一个类型(sentinel_t)。
参数类型对付函数署名是必要的,但我们不须要值。
所有必要的便是将当前迭代器与哨兵进行比较。

每当你有一个没有预定终点进行比较的类型或类时,这种技能都该当很有用。

标签:

相关文章

Python编程从入门到精通,探索编程之美

编程已经成为现代社会的一项基本技能。Python作为一种简单易学、功能强大的编程语言,在我国教育领域备受关注。本文将从Python...

网站推广 2025-03-02 阅读1 评论0

Scum07代码编程之美与适用方法

编程已成为当今社会不可或缺的技能之一。Scum07代码作为一款经典的编程语言,在我国众多程序员中备受推崇。本文将深入解析Scum0...

网站推广 2025-03-02 阅读1 评论0

Linux环境下的前端代码运行优化与步骤

前端技术逐渐成为软件开发的核心。Linux操作系统因其稳定性、安全性、开放性等特点,成为众多开发者和企业青睐的运行环境。本文将从L...

网站推广 2025-03-02 阅读1 评论0