在C中循环TWICE最优雅的方法是什么

Xof*_*ofo 16 c iterator loops

很多时候我需要在for循环中做两件事.简单地说,我可以使用迭代器设置for循环并进行两次:

for (i = 0; i < 2; i++)
{
 // Do stuff
}
Run Code Online (Sandbox Code Playgroud)

现在我有兴趣尽可能简单地做这个,也许没有初始化器或迭代器?有没有其他的,非常简单和优雅的方法来实现这一目标?

Ila*_*lan 58

这很优雅,因为它看起来像一个三角形; 和三角形是优雅的.

i = 0; 
here: dostuff(); 
i++; if ( i == 1 ) goto here;
Run Code Online (Sandbox Code Playgroud)

  • +1以嘲笑OP的要求的模糊性让我发笑 (20认同)
  • @Les:我认为这里的转到是嘲弄的一部分. (4认同)
  • -1为goto,但我同意'R',所以net 0. (3认同)
  • +1但你的最后一个语句以冒号而不是分号结尾.修正错字. (2认同)
  • -1:这很有趣,但实际上不应该是问题的最佳答案. (2认同)
  • 这是有史以来最糟糕的方法 (2认同)

Jor*_*dão 35

将其封装在一个函数中并调用它两次.

void do_stuff() {
  // Do Stuff
}

// .....

do_stuff();
do_stuff();
Run Code Online (Sandbox Code Playgroud)

注意:如果在填充逻辑中使用封闭函数的变量或参数,则可以将它们作为参数传递给提取的 do_stuff函数.

  • 如果你内联函数,你甚至不会有函数调用开销 (2认同)

abe*_*nky 30

如果它只有两次,并且你想避免循环,那就写两次darn的东西吧.

statement1;
statement1;  // (again)
Run Code Online (Sandbox Code Playgroud)


qui*_*ars 16

如果循环对你来说太冗长,你也可以为它定义一个别名:

#define TWICE for (int _index = 0; _index < 2; _index++)
Run Code Online (Sandbox Code Playgroud)

这将导致该代码:

TWICE {
    // Do Stuff
}

// or

TWICE
    func();
Run Code Online (Sandbox Code Playgroud)

我只建议使用这个宏,如果你必须经常这样做,我认为普通的for循环更具可读性.

  • `TWICE {TWICE ...}`oops. (7认同)
  • @jweyrich:由于两个变量声明都在不同的范围内,第二个_index应该遮蔽第一个,因此它应该起作用.但说实话,我还没有尝试过. (5认同)

phi*_*mue 9

不幸的是,不适用于C,但仅适用于C++,但完全符合您的要求:

只需包含标题,您可以编写如下内容:

10 times {
  // Do stuff
}
Run Code Online (Sandbox Code Playgroud)

我也会尝试为C重写它.

  • 我希望+1为语言的出色有用和可读的滥用,但我认为这不适用于C. :( (2认同)

phi*_*mue 8

所以,过了一段时间,这里有一种方法可以让你在纯C中编写以下内容:

2 times {
  do_something()
}
Run Code Online (Sandbox Code Playgroud)

例:

你必须将这个小东西包含在一个简单的头文件中(我总是称之为文件extension.h).然后,您将能够以下列风格编写程序:

#include<stdio.h>
#include"extension.h"

int main(int argc, char** argv){
    3 times printf("Hello.\n");
    3 times printf("Score: 0 : %d\n", _);
    2 times {
        printf("Counting: ");
        9 times printf("%d ", _);
        printf("\n");
    }
    5 times {
        printf("Counting up to %d: ", _);
        _ times printf("%d ", _);
        printf("\n");
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

特征:

  • 简单循环的简单表示法(在上面描述的样式中)
  • Counter隐式存储在一个名为_(简单下划线)的变量中.
  • 允许嵌套循环.

限制(以及如何(部分)规避它们):

  • 仅适用于一定数量的循环(当然是" - 当然" - 合理,因为您只想将这样的东西用于"小"循环).当前实现最多支持18次迭代(较高的值会导致未定义的行为).可以通过更改数组的大小在头文件中进行调整_A.
  • 只允许一定的嵌套深度.当前实现支持嵌套深度10.可以通过重新定义宏来调整_Y.

说明:

你可以在这里看到完整的(=去混淆的)源代码.假设我们想要允许多达18个循环.

  • 检索上层迭代边界:基本思想是拥有一个char最初都设置为0的数组(这是数组counterarray).如果我们发出一个调用例如2 times {do_it;}, times应该将第二个元素设置counterarray1(即counterarray[2] = 1).在C中,可以在这样的赋值中交换索引和数组名称,因此我们可以写入2[counterarray] = 1相同的操作.这正是宏times作为第一步所做的事情.然后,我们可以稍后扫描数组,counterarray直到找到一个不为0的元素,但是1.相应的索引就是上面的迭代边界.它存储在变量中searcher.由于我们想要支持嵌套,我们必须分别存储每个嵌套深度的上限,这是通过searchermax[depth]=searcher+1.
  • 调整当前嵌套深度:如上所述,我们希望支持循环嵌套,因此我们必须跟踪当前嵌套深度(在变量中完成depth).如果我们开始这样的循环,我们将它增加1.
  • 实际的计数器变量:我们有一个"变量",它被_隐式地分配给当前的计数器.实际上,我们为每个嵌套深度存储一个计数器(全部存储在数组中counter.然后,_只是另一个宏从该数组中检索当前嵌套深度的正确计数器.
  • 实际的for循环:我们将for循环分成几部分:
    • 我们将当前嵌套深度的计数器初始化为0(完成counter[depth] = 0).
    • 迭代步骤是最复杂的部分:我们必须检查当前嵌套深度的循环是否已达到其结束.如果是这样,我们会相应地更新嵌套深度.如果不是,我们必须将当前嵌套深度的计数器增加1. lastloop如果这是最后一次迭代,则变量为1,否则为0,我们相应地调整当前嵌套深度.这里的主要问题是我们必须将它写成一个表达式序列,所有表达式都用逗号分隔,这要求我们以非常直接的方式编写所有这些条件.
    • for循环的"递增步骤"仅包含一个赋值,它递增适当的计数器(即counter正确嵌套深度的元素)并将该值赋给我们的"计数器变量" _.

  • @ChrisLutz说实话,我不打算允许这个,但现在已经完成了,让我们把它称为一个功能:) (2认同)

小智 4

那这个呢??

void DostuffFunction(){}

for (unsigned i = 0; i < 2; ++i, DostuffFunction());
Run Code Online (Sandbox Code Playgroud)

问候,巴勃罗。