【问题标题】:How is the "for" statement constructed? [closed]“for”语句是如何构造的? [关闭]
【发布时间】:2015-09-28 20:41:50
【问题描述】:

每个人都知道 for 最常见的用法:(0 - 9)

for (int i = 0; i < 10; i++)

不过,我也看到了一些不太常见的版本,例如 (1 - 10)

for (int i = 0; i++ < 10;)

或 (1 - 10)

int i = 0;
for (;i++ < 10;)

这表明循环可能比我想象的更可定制。如果我猜对了,那似乎是

  1. 总是需要用 2 个分号来分隔 3 个可选语句
  2. 第二个语句需要转换为布尔值 1 才能继续循环
  3. 第一个语句是我唯一可以声明变量并被调用一次的语句
  4. 第三条和第二条语句在每次迭代后调用,可以包含任何内容(除了声明)
  5. 只要满足这些条件,我可以做任何事情

例如 (0, 3, 7)

for (int i = 0, j = 2; i < 10; i+=++j)

这些类型的 for 循环是否被视为该语言的标准用法?或者只是由于 msvc++ 中的实现设计而发生的事情?关于 for 循环的规则究竟是什么的任何官方说明?

【问题讨论】:

  • 这对开始有好处:en.cppreference.com/w/cpp/language/for
  • 我会为您的第三个示例使用 while 循环,因为您使用的只是条件部分。
  • 我不明白你的问题。它已经很好地记录了,for 循环表达式部分是什么,以及它们何时执行。你需要分号来表示你想省略的部分,是的。

标签: c++ language-lawyer


【解决方案1】:

你是对的。不过……

仅仅因为它是可能的并不意味着你应该这样做。 “for”循环的全部目的是它应该组织在任何有能力的程序员都能快速理解的水平上。一个关键的基础是程序员应该知道“for”循环将运行多长时间。如果你给所教的内容增加了更多的复杂性,“for”循环的意义就消失了。我无法轻易查看您的第三个示例并判断循环将迭代多长时间。

如果您需要像第三个示例那样使用“for”循环,最好编写一个 while/do-while 循环。

【讨论】:

    【解决方案2】:

    来自 ISO C99 草案:

    for ( clause-1 ; expression-2 ; expression-3 ) 语句表现为 如下:

    表达式 expression-2 是控制表达式 在每次执行循环体之前对其进行评估。

    表达式 expression-3 在每个表达式之后被评估为 void 表达式 循环体的执行。

    如果第 1 条是声明,则 它声明的任何标识符都是声明的其余部分,并且 整个循环,包括其他两个表达式;它到达 在第一次评估控制之前的执行顺序 表达。

    如果 Clause-1 是一个表达式,它被评估为 void 控制的第一次评估之前的表达式 表达。

    clause-1 和 expression-3 都可以省略。一个 省略的表达式 2 被一个非零常量替换。

    回答您的问题:

    1. 总是需要用 2 个分号来分隔 3 个可选语句

      是的。

    2. 第二条语句需要转换为布尔值 1 才能继续循环。

      是的。第二个语句将评估为布尔真/假(尽管不一定是“1”)。

    3. 第一个语句是唯一可以声明变量并被调用一次的语句

      对于 C++,是的。在 C(C99 之前)中,您必须在 for 循环之外声明变量。

    4. 第三条和第二条语句在每次迭代后调用,可以包含任何内容(除了声明)

      是的。它们可能什么都没有。例如,for ( ;; ) 表示“永远循环”。 只要满足这些条件,我可以做任何事情

    这是一个很好的教程:

    【讨论】:

    • for(int x:vec) 想要一个带有“始终需要 2 个分号来分隔 3 个可选语句”的词
    【解决方案3】:

    我个人最喜欢的一个是遍历链表:

    for(Node *p = head; p; p = p->next)  ... 
    

    当然,如果你做“无条件”,你会得到一个无限循环:

    for(;;) ... 
    

    但是是的,只要for( 后跟有效语句、两个分号和),它就是“好代码”。

    for(printf("h"); !printf("world\n"); printf("ello, "));
    

    是有效的,如果相当奇怪的 C 代码(和 C++,但 cout 是首选)。

    当然,“它可以编译并执行您所期望的”并不能使它正确或很好地使用该语言。如果其他人能够阅读代码并理解其用途,并且不想去其他地方工作或对最初编写代码的人实施暴力,则通常是首选。

    【讨论】:

    • 我实际上更喜欢for(Node *p = head; p != nullptr; p = p-&gt;next) p = p-&gt;next 是一个很好的增量。
    • 当然,如果你愿意,你可以写出更长的p != nullptr;。它做了完全相同的事情,但使它更清晰[我的工作实际上允许整体构造,但循环中需要nullptr != p;]
    • 为什么要打印"hworld\n"?似乎很奇怪。我想这是一个偶然的例子,说明为什么花哨的 for 循环是个坏主意。
    【解决方案4】:

    这取决于你想怎么做。 C++ 很灵活,允许您根据需要构建语句。当然,更清晰的方式更可取。

    “for”语句有 3 个部分,用“;”分隔人物:

    1) 初始化代码 (int i = 0):在其中初始化将在循环中使用的计数器变量;

    2) 循环条件 (i

    3) step(increment):可以选择指定计数器变量的增量;

    当您知道要迭代(循环)多少次时,“for”语句更可取并指示使用。否则,建议使用“while”。

    C++ 灵活性示例:

    for(int i = 0; i < 20; i++) { }
    

    等价于

    int i = 0;    
    for(;i < 20;) { i++; }
    

    【讨论】:

      猜你喜欢
      • 2018-10-18
      • 2017-08-28
      • 1970-01-01
      • 2014-02-10
      • 2017-07-08
      • 2016-09-08
      • 2014-09-30
      • 1970-01-01
      • 2021-11-10
      相关资源
      最近更新 更多