#step #macro #condition #loops #c-style #continue #initialization

cfor

一个宏,为 Rust 提供了 C 风格的 for 循环,包括初始化、条件和步长。它正确处理控制流,如 continue 和 break。

6 个版本 (2 个稳定版)

使用旧 Rust 2015

1.1.0 2015 年 11 月 14 日
1.0.0 2015 年 5 月 25 日
0.2.1 2015 年 3 月 2 日
0.2.0 2015 年 1 月 20 日
0.1.1 2014 年 11 月 14 日

2044Rust 模式 中排名

Download history 11/week @ 2024-02-16 17/week @ 2024-02-23 12/week @ 2024-03-01 15/week @ 2024-03-08 15/week @ 2024-03-15 16/week @ 2024-03-22 38/week @ 2024-03-29

每月 86 次下载
用于 2 crates

MIT/Apache

12KB

包含 (ELF 可执行文件/库, 7KB) 一个.out

Rust 的 C 风格 for 循环

Build Status Coverage Status

一个实现 C 风格 for 循环的 Rust 宏。有关更多信息,请参阅文档


lib.rs:

以宏形式实现的 C 风格 for 循环。

其形式为 cfor!(初始化器; 条件; 步长 { 主体 })

  • 初始化器 是在循环任何迭代之前评估的语句。在此处声明的任何变量都限于 cfor! 调用的作用域内,即在 条件步长主体 内仅可用。
  • 条件 是在每次迭代开始时评估的布尔表达式。如果它评估为 false,则迭代将停止。
  • 步长 是一个任意表达式,它在每次迭代结束时执行(包括如果调用 continue),在检查 条件 之前。

初始化器和条件可以像 C 一样为空,但步长不能。没有步长的 for 循环与 while 循环相同。

源代码 & 问题跟踪器

何时使用它?

只有在 cfor! 比更声明性的内置 迭代器它们的适配器for 循环更清晰时,才使用。例如,内置迭代器功能更自包含,因此更不容易在期望 j 的位置不小心写入 i(我写 C 中的嵌套 "2D" 循环时,经常会因为这个原因而受到影响)。

此外,上述适配器方法允许以无法通过 C 风格迭代实现的方式编写简洁、高效、可重用的 "函数式" 代码。

如何使用它?

将存储库作为正常的 cargo 依赖项添加,并使用以下命令将其包含到您的 crate 中:#[phase(plugin)]。(请参阅以下示例。)

[dependencies.cfor]
cfor = "1.0"

示例

简单

std::iter 不太自然地处理非加性条件,但可以简单地直接处理。

#[macro_use] extern crate cfor;

fn main() {
    cfor!{let mut x = 1; x < 0x1000; x *= 2; {
        println!("power of 2: {}", x);
    }}
}

体内条件

如果某个条件需要执行一些额外的计算来检查(或者如果有一些代码应该始终被评估,即使对于给定的迭代条件将是 false),则可以在 cfor 头部省略该条件。

#[macro_use] extern crate cfor;

fn main() {
    cfor!{let mut x = 1; ; x *= 2; {
        // ... setup ...
        println!("handling power of 2: {}", x);

        if x < 0x1000 { break }

        // ... further handling ...
        println!("handling power of 2: {}", x);
    }}
}

循环外的初始化

有时,在循环完成后可能希望访问循环外部的变量,因此必须在循环外声明它,或者可能正在遍历一些预先提供的/计算出的值,因此没有有意义的其他初始化。在这种情况下,可以安全地省略初始化表达式。

#[macro_use] extern crate cfor;

extern crate rand;

fn main() {
    let mut x = 1u16;

    cfor!{; x < 0x1000; x *= 2; {
        println!("power of 2: {}", x);

        // sometimes quit early
        if x > rand::random() { break }
    }}

    println!("actually stopped at {}", x);
}

处理 continue

(或,“为什么这个宏如此复杂?”)

特别努力确保 continue 正确地工作,以下定义的原始宏会导致 continue 也跳过评估 step,这可能导致无限循环等不希望的行为。

// WARNING: this is broken.
macro_rules! bad_cfor {
    ($init: stmt; $cond: expr; $step: expr; $body: block) => {
        {
            $init;
            while $cond {
                $body;

                $step;
            }
        }
    }
}

fn main() {
    let mut true_counter = 0;

    bad_cfor!{let mut i = 0; i < 10; i += 1; {

        // manually avoid the infinite loop
        if true_counter >= 50 { break }
        true_counter += 1;

        println!("i = {}", i);
        // try to skip just i == 4
        if i == 4 {
            // but this skips the i += 1 leaving us
            // on i == 4 forever.
            continue
        }
        // ...more code...
    }}
}

它以与 cfor! 相同的方式调用,但如果 $body 包含 continue,则循环体末尾的 $step 将永远不会被评估。

处理多个初始化和步骤

与 C 循环一样,cfor! 支持使用逗号分隔指定多个初始化和步骤。

#[macro_use] extern crate cfor;

fn main() {
    cfor!{let mut x = 0, let mut y = x; x <= 10 && y <= 100; x += 1, y += 10; {
        println!("x: {}, y: {}", x, y);
    }}
}

无运行时依赖