在C中循环两次最优雅的方式是什么

时间:2021-04-24 00:16:57

Many times I need to do things TWICE in a for loop. Simply I can set up a for loop with an iterator and go through it twice:

很多时候我需要在for循环中做两次事情。简单地说,我可以用迭代器设置一个for循环,然后遍历两次:

for (i = 0; i < 2; i++)
{
 // Do stuff
}

Now I am interested in doing this as SIMPLY as I can, perhaps without an initializer or iterator? Are there any other, really simple and elegant, ways of achieving this?

现在我感兴趣的是尽可能简单地做这件事,也许没有初始化器或迭代器?有没有其他简单而优雅的方法来实现这一点?

23 个解决方案

#1


3  

What about this??

这是什么? ?

void DostuffFunction(){}

for (unsigned i = 0; i < 2; ++i, DostuffFunction());

Regards, Pablo.

问候,巴勃罗。

#2


56  

This is elegant because it looks like a triangle; and triangles are elegant.

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

i = 0; 
here: dostuff(); 
i++; if ( i == 1 ) goto here;

#3


34  

Encapsulate it in a function and call it twice.

将它封装在函数中并调用两次。

void do_stuff() {
  // Do Stuff
}

// .....

do_stuff();
do_stuff();

Note: if you use variables or parameters of the enclosing function in the stuff logic, you can pass them as arguments to the extracted do_stuff function.

注意:如果您在stuff逻辑中使用随附函数的变量或参数,您可以将它们作为参数传递给提取的do_stuff函数。

#4


30  

If its only twice, and you want to avoid a loop, just write the darn thing twice.

如果它只有两次,而你想要避免循环,那就写两次。

statement1;
statement1;  // (again)

#5


16  

If the loop is too verbose for you, you can also define an alias for it:

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

#define TWICE for (int _index = 0; _index < 2; _index++)

This would result into that code:

这将导致该守则:

TWICE {
    // Do Stuff
}

// or

TWICE
    func();

I would only recommend to use this macro if you have to do this very often, I think else the plain for-loop is more readable.

我只建议您使用这个宏,如果您必须经常这样做的话,我认为plain for-loop更易于阅读。

#6


8  

Unfortunately, this is not for C, but for C++ only, but does exactly what you want:

不幸的是,这不是针对C的,而是针对c++的,但它确实实现了您想要的:

Just include the header, and you can write something like this:

只包括标题,你可以这样写:

10 times {
  // Do stuff
}

I'll try to rewrite it for C as well.

我试着把C也重写一遍。

#7


8  

So, after some time, here's an approach that enables you to write the following in pure C:

所以,过了一段时间,有一种方法可以让你用纯C来写以下内容:

2 times {
  do_something()
}

Example:

You'll have to include this little thing as a simple header file (I always called the file extension.h). Then, you'll be able to write programs in the style of:

您必须将这个小东西包含为一个简单的头文件(我一直把它称为file 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;
}

Features:

  • Simple notation of simple loops (in the style depicted above)
  • 简单循环表示法(如上所示)
  • Counter is implicitly stored in a variable called _ (a simple underscore).
  • 计数器隐式存储在名为_(简单下划线)的变量中。
  • Nesting of loops allowed.
  • 允许嵌套循环。

Restrictions (and how to (partially) circumvent them):

  • Works only for a certain number of loops (which is - "of course" - reasonable, since you only would want to use such a thing for "small" loops). Current implementation supports a maximum of 18 iterations (higher values result in undefined behaviour). Can be adjusted in header file by changing the size of array _A.
  • 只适用于一定数量的循环(“当然”),因为您只希望将这样的东西用于“小”循环)。当前实现支持最多18次迭代(更高的值导致未定义的行为)。可以通过改变数组_A的大小在头文件中进行调整。
  • Only a certain nesting depth is allowed. Current implementation supports a nesting depth of 10. Can be adjusted by redefining the macro _Y.
  • 只允许一定的嵌套深度。当前实现支持嵌套深度为10。可以通过重新定义宏_Y进行调整。

Explanation:

You can see the full (=de-obfuscated) source-code here. Let's say we want to allow up to 18 loops.

您可以在这里看到完整的(消除混淆)源代码。假设我们要允许最多18个循环。

  • Retrieving upper iteration bound: The basic idea is to have an array of chars that are initially all set to 0 (this is the array counterarray). If we issue a call to e.g. 2 times {do_it;}, the macro times shall set the second element of counterarray to 1 (i.e. counterarray[2] = 1). In C, it is possible to swap index and array name in such an assignment, so we can write 2[counterarray] = 1 to acchieve the same. This is exactly what the macro times does as first step. Then, we can later scan the array counterarray until we find an element that is not 0, but 1. The corresponding index is then the upper iteration bound. It is stored in variable searcher. Since we want to support nesting, we have to store the upper bound for each nesting depth separately, this is done by searchermax[depth]=searcher+1.
  • 检索上迭代界:基本思想是拥有一个chars数组,这些chars最初都设置为0(这是数组反数组)。如果我们发出调用。2 * { do_it;},宏*应当设置counterarray的第二个元素1(即counterarray[2]= 1)。在C语言中,可以互换指数和数组名在这样一个任务,所以我们可以写2[counterarray]= 1人们相同的。这正是宏观时代所做的第一步。然后,我们可以稍后扫描数组反数组,直到找到一个不是0而是1的元素。相应的索引就是上迭代界。它存储在变量搜索器中。由于我们想要支持嵌套,所以我们必须单独存储每个嵌套深度的上限,这是由searchermax[depth]=searcher+1完成的。
  • Adjusting current nesting depth: As said, we want to support nesting of loops, so we have to keep track of the current nesting depth (done in the variable depth). We increment it by one if we start such a loop.
  • 调整当前嵌套深度:如前所述,我们希望支持循环嵌套,因此我们必须跟踪当前嵌套深度(在可变深度中完成)。如果我们开始这样的循环,我们将它增加1。
  • The actual counter variable: We have a "variable" called _ that implicitly gets assigned the current counter. In fact, we store one counter for each nesting depth (all stored in the array counter. Then, _ is just another macro that retrieves the proper counter for the current nesting depth from this array.
  • 实际的计数器变量:我们有一个名为_的“变量”,它隐式地分配当前计数器。实际上,我们为每个嵌套深度存储一个计数器(所有存储在数组计数器中)。然后,_只是另一个宏,它从这个数组中检索当前嵌套深度的适当计数器。
  • The actual for loop: We take the for loop into parts:
    • We initialize the counter for the current nesting depth to 0 (done by counter[depth] = 0).
    • 我们将当前嵌套深度的计数器初始化为0(由counter[depth] = 0完成)。
    • The iteration step is the most complicated part: We have to check if the loop at the current nesting depth has reached its end. If so, we have do update the nesting depth accordingly. If not, we have to increment the current nesting depth's counter by 1. The variable lastloop is 1 if this is the last iteration, otherwise 0, and we adjust the current nesting depth accordingly. The main problem here is that we have to write this as a sequence of expressions, all separated by commata, which requires us to write all these conditions in a very non-straight-forward way.
    • 迭代步骤是最复杂的部分:我们必须检查在当前嵌套深度上的循环是否已经结束。如果是这样,我们将相应地更新嵌套深度。如果没有,我们必须将当前嵌套深度计数器增加1。如果这是最后一次迭代,变量lastloop是1,否则为0,我们相应地调整当前嵌套深度。这里的主要问题是我们必须把它写成一个表达式的序列,所有的表达式都用逗号分开,这就要求我们以非常不直接的方式写出所有的条件。
    • The "increment step" of the for loop consists of only one assignment, that increments the appropriate counter (i.e. the element of counter of the proper nesting depth) and assigns this value to our "counter variable" _.
    • for循环的“增量步骤”只包含一个赋值,该赋值增加适当的计数器(即适当嵌套深度的计数器的元素),并将该值赋给我们的“计数器变量”_。
  • 实际的for循环:我们考虑for循环部分:我们初始化计数器当前嵌套深度为0(由计数器(深度)= 0)。迭代步骤是最复杂的部分:我们必须检查当前的循环嵌套深度已经结束了。如果是这样,我们将相应地更新嵌套深度。如果没有,我们必须将当前嵌套深度计数器增加1。如果这是最后一次迭代,变量lastloop是1,否则为0,我们相应地调整当前嵌套深度。这里的主要问题是我们必须把它写成一个表达式的序列,所有的表达式都用逗号分开,这就要求我们以非常不直接的方式写出所有的条件。for循环的“增量步骤”只包含一个赋值,该赋值增加适当的计数器(即适当嵌套深度的计数器的元素),并将该值赋给我们的“计数器变量”_。

#8


4  

What abelenky said.

abelenky所说的。

And if your { // Do stuff } is multi-line, make it a function, and call that function -- twice.

如果你的{// Do stuff}是多行,使它成为一个函数,并调用那个函数——两次。

#9


3  

Another attempt:

另一个尝试:

for(i=2;i--;) /* Do stuff */

This solution has many benefits:

这个解决方案有很多好处:

  • Shortest form possible, I claim (13 chars)
  • 我要求最短的表格(13个字符)
  • Still, readable
  • 不过,可读
  • Includes initialization
  • 包括初始化
  • The amount of repeats ("2") is visible in the code
  • 重复的数量(“2”)在代码中是可见的
  • Can be used as a toggle (1 or 0) inside the body e.g. for alternation
  • 可以用作在身体内的开关(1或0),例如更换
  • Works with single instruction, instruction body or function call
  • 适用于单指令、指令体或函数调用。
  • Flexible (doesn't have to be used only for "doing twice")
  • 灵活(不必只用于“做两次”)
  • Dijkstra compliant ;-)
  • Dijkstra算法兼容;-)

From comment:

评论:

for (i=2; i--; "Do stuff");

#10


2  

Use function:

使用功能:

func();
func();

Or use macro (not recommended):

或使用宏(不推荐):

#define DO_IT_TWICE(A) A; A

DO_IT_TWICE({ x+=cos(123); func(x); })

#11


2  

If your compiler supports this just put the declaration inside the for statement:

如果您的编译器支持这一点,请将声明放在for语句中:

for (unsigned i = 0; i < 2; ++i)
{
 // Do stuff
}

This is as elegant and efficient as it can be. Modern compilers can do loop unrolling and all that stuff, trust them. If you don't trust them, check the assembler.

这是最优雅和有效的。现代编译器可以做循环展开等等,相信它们。如果您不信任它们,请检查汇编程序。

And it has one little advantage to all other solutions, for everybody it just reads, "do it twice".

它对所有其他的解决方案都有一个小优势,对每个人来说,它只是写着“做两次”。

#12


2  

Many people suggest writing out the code twice, which is fine if the code is short. There is, however, a size of code block which would be awkward to copy but is not large enough to merit its own function (especially if that function would need an excessive number of parameters). My own normal idiom to run a loop 'n' times is

许多人建议把代码写两次,如果代码很短,这是可以的。但是,有一个代码块的大小是难以复制的,但是它的大小并不能满足其本身的功能(特别是当该函数需要过多的参数时)。我自己循环n次的习惯用法是

  i = number_of_reps;
  do
  {
    ... whatever
  } while(--i);

In some measure because I'm frequently coding for an embedded system where the up-counting loop is often inefficient enough to matter, and in some measure because it's easy to see the number of repetitions. Running things twice is a bit awkward because the most efficient coding on my target system

在某种程度上,因为我经常为一个嵌入式系统编写代码,在这个系统中,向上计数循环的效率非常低,这很重要,在某种程度上,因为它很容易看到重复的次数。两次运行东西有点尴尬,因为目标系统上最高效的编码

  bit rep_flag;

  rep_flag = 0;
  do
  {
    ...
  } while(rep_flag ^= 1); /* Note: if loop runs to completion, leaves rep_flag clear */

doesn't read terribly well. Using a numeric counter suggests the number of reps can be varied arbitrarily, which in many instances won't be the case. Still, a numeric counter is probably the best bet.

并没有很好的阅读。使用数字计数器表明,代表的数量可以任意变化,在许多情况下不是这样的。不过,数字计数器可能是最好的选择。

#13


2  

Assuming C++0x lambda support:

假设c++ 0 xλ支持:

template <typename T> void twice(T t)
{
    t();
    t();
}

twice([](){ /*insert code here*/ });

Or:

或者:

twice([]()
{ 
    /*insert code here*/ 
});

Which doesn't help you since you wanted it for C.

这对你没有帮助,因为你想要C。

#14


2  

As Edsger W. Dijkstra himself put it : "two or more, use a for". No need to be any simpler.

正如Edsger W. Dijkstra自己所言:“两个或更多,使用a for”。没有必要再简单了。

#15


1  

Good rule: three or more, do a for.

好的规则:三个或更多,做a for。

I think I read that in Code Complete, but I could be wrong. So in your case you don't need a for loop.

我想我在《代码完成》中读到过,但我可能错了。在你的例子中,你不需要一个for循环。

#16


1  

This is the shortest possible without preprocessor/template/duplication tricks:

这是没有预处理器/模板/复制技巧的最短时间:

for(int i=2; i--; ) /*do stuff*/;

Note that the decrement happens once right at the beginning, which is why this will loop precisely twice with the indices 1 and 0 as requested.

注意,减量在一开始就发生了一次,这就是为什么它会按照要求对索引1和0进行两次精确的循环。

Alternatively you can write

或者你可以写

for(int i=2; i--; /*do stuff*/) ;

But that's purely a difference of taste.

但这纯粹是口味的不同。

#17


0  

If what you are doing is somewhat complicated wrap it in a function and call that function twice? (This depends on how many local variables your do stuff code relies on).

如果你所做的是有点复杂的将它封装到一个函数中并调用该函数两次?(这取决于do代码所依赖的本地变量的数量)。

You could do something like

你可以这样做

void do_stuff(int i){
    // do stuff
}

do_stuff(0);
do_stuff(1);

But this may get extremely ugly if you are working on a whole bunch of local variables.

但是如果你研究大量的局部变量,这可能会变得非常糟糕。

#18


0  

//dostuff
  stuff;
//dostuff (Attention I am doing the same stuff for the :**2nd** time)
  stuff;

#19


0  

First, use a comment

首先,使用一个评论

/* Do the following stuff twice */

then,
1) use the for loop
2) write the statement twice, or
3) write a function and call the function twice
do not use macros, as earlier stated, macros are evil.

然后,1)使用for循环2)将语句写两次,或者3)写一个函数,并调用函数两次不使用宏,如前所述,宏是邪恶的。

(My answer's almost a triangle)

(我的答案几乎是一个三角形)

#20


0  

What is elegance? How do you measure it? Is someone paying you to be elegant? If so how do they determine the dollar-to-elegance conversion?

什么是优雅?你如何衡量它?有人付钱让你优雅吗?如果是这样,他们如何确定美元对优雅的转换?

When I ask myself, "how should this be written," I consider the priorities of the person paying me. If I'm being paid to write fast code, control-c, control-v, done. If I'm being paid to write code fast, well.. same thing. If I'm being paid to write code that occupies the smallest amount of space on the screen, I short the stock of my employer.

当我问自己,“这应该怎么写”时,我考虑了支付给我的人的优先顺序。如果我被雇来写快速代码,control-c, control-v,完成。如果我被雇来写代码快的话。同样的事情。如果有人付钱让我写代码,让我在屏幕上占据最小的空间,我就会做空雇主的股票。

#21


0  

jump instruction is pretty slow,so if you write the lines one after the other,it would work faster,than writing a loop. but modern compilers are very,very smart and the optimizations are great (if they are allowed,of course). if you have turned on your compiler's optimizations,you don't care the way,you write it - with loop or not (:

跳转指令非常慢,所以如果你一个接一个地写行,它的工作速度会比写一个循环快。但现代编译器非常非常聪明,优化也很棒(当然,如果允许的话)。如果你已经打开了编译器的优化,你不关心怎么写,你可以用循环来写(

EDIT : http://en.wikipedia.org/wiki/compiler_optimizations just take a look (:

编辑:http://en.wikipedia.org/wiki/compile er_optimization ations看看(:

#22


0  

Close to your example, elegant and efficient:

接近你的例子,优雅而高效:

for (i = 2; i; --i)
{
    /* Do stuff */
}

Here's why I'd recommend that approach:

以下是我推荐这种方法的原因:

  • It initializes the iterator to the number of iterations, which makes intuitive sense.
  • 它初始化迭代器到迭代的次数,这很直观。
  • It uses decrement over increment so that the loop test expression is a comparison to zero (the "i;" can be interpreted as "is i true?" which in C means "is i non-zero"), which may optimize better on certain architectures.
  • 它使用递减而不是递增,因此循环测试表达式是与零的比较(“i;”可以被解释为“我是真的吗?”,在C中表示“我是非零的”),这可以更好地优化某些体系结构。
  • It uses pre-decrement as opposed to post-decrement in the counting expression for the same reason (may optimize better).
  • 它在计数表达式中使用预减量而不是后减量,原因是相同的(可以优化得更好)。
  • It uses a for loop instead of do/while or goto or XOR or switch or macro or any other trick approach because readability and maintainability are more elegant and important than clever hacks.
  • 它使用for循环,而不是do/while、goto、XOR、switch、macro或任何其他技巧方法,因为可读性和可维护性比聪明的黑客更优雅、更重要。
  • It doesn't require you to duplicate the code for "Do stuff" so that you can avoid a loop. Duplicated code is an abomination and a maintenance nightmare.
  • 它不需要您为“Do stuff”复制代码,以便您可以避免循环。重复的代码是令人厌恶的,也是维护的梦魇。

If "Do stuff" is lengthy, move it into a function and give the compiler permission to inline it if beneficial. Then call the function from within the for loop.

如果“Do stuff”很长,那么将它移动到函数中,并给编译器以内联的权限。然后调用for循环中的函数。

#23


-1  

void loopTwice (bool first = true)
{
    // Recursion is your friend
    if (first) {loopTwice(false);}

    // Do Stuff
    ...
}

I'm sure there's a more elegant way, but this is simple to read, and pretty simply to write. There might even be a way to eliminate the bool parameter, but this is what I came up with in 20 seconds.

我肯定有一种更优雅的方式,但这很容易读,写起来也很简单。甚至可能有一种方法可以消除bool参数,但这就是我在20秒内得出的结果。

#1


3  

What about this??

这是什么? ?

void DostuffFunction(){}

for (unsigned i = 0; i < 2; ++i, DostuffFunction());

Regards, Pablo.

问候,巴勃罗。

#2


56  

This is elegant because it looks like a triangle; and triangles are elegant.

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

i = 0; 
here: dostuff(); 
i++; if ( i == 1 ) goto here;

#3


34  

Encapsulate it in a function and call it twice.

将它封装在函数中并调用两次。

void do_stuff() {
  // Do Stuff
}

// .....

do_stuff();
do_stuff();

Note: if you use variables or parameters of the enclosing function in the stuff logic, you can pass them as arguments to the extracted do_stuff function.

注意:如果您在stuff逻辑中使用随附函数的变量或参数,您可以将它们作为参数传递给提取的do_stuff函数。

#4


30  

If its only twice, and you want to avoid a loop, just write the darn thing twice.

如果它只有两次,而你想要避免循环,那就写两次。

statement1;
statement1;  // (again)

#5


16  

If the loop is too verbose for you, you can also define an alias for it:

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

#define TWICE for (int _index = 0; _index < 2; _index++)

This would result into that code:

这将导致该守则:

TWICE {
    // Do Stuff
}

// or

TWICE
    func();

I would only recommend to use this macro if you have to do this very often, I think else the plain for-loop is more readable.

我只建议您使用这个宏,如果您必须经常这样做的话,我认为plain for-loop更易于阅读。

#6


8  

Unfortunately, this is not for C, but for C++ only, but does exactly what you want:

不幸的是,这不是针对C的,而是针对c++的,但它确实实现了您想要的:

Just include the header, and you can write something like this:

只包括标题,你可以这样写:

10 times {
  // Do stuff
}

I'll try to rewrite it for C as well.

我试着把C也重写一遍。

#7


8  

So, after some time, here's an approach that enables you to write the following in pure C:

所以,过了一段时间,有一种方法可以让你用纯C来写以下内容:

2 times {
  do_something()
}

Example:

You'll have to include this little thing as a simple header file (I always called the file extension.h). Then, you'll be able to write programs in the style of:

您必须将这个小东西包含为一个简单的头文件(我一直把它称为file 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;
}

Features:

  • Simple notation of simple loops (in the style depicted above)
  • 简单循环表示法(如上所示)
  • Counter is implicitly stored in a variable called _ (a simple underscore).
  • 计数器隐式存储在名为_(简单下划线)的变量中。
  • Nesting of loops allowed.
  • 允许嵌套循环。

Restrictions (and how to (partially) circumvent them):

  • Works only for a certain number of loops (which is - "of course" - reasonable, since you only would want to use such a thing for "small" loops). Current implementation supports a maximum of 18 iterations (higher values result in undefined behaviour). Can be adjusted in header file by changing the size of array _A.
  • 只适用于一定数量的循环(“当然”),因为您只希望将这样的东西用于“小”循环)。当前实现支持最多18次迭代(更高的值导致未定义的行为)。可以通过改变数组_A的大小在头文件中进行调整。
  • Only a certain nesting depth is allowed. Current implementation supports a nesting depth of 10. Can be adjusted by redefining the macro _Y.
  • 只允许一定的嵌套深度。当前实现支持嵌套深度为10。可以通过重新定义宏_Y进行调整。

Explanation:

You can see the full (=de-obfuscated) source-code here. Let's say we want to allow up to 18 loops.

您可以在这里看到完整的(消除混淆)源代码。假设我们要允许最多18个循环。

  • Retrieving upper iteration bound: The basic idea is to have an array of chars that are initially all set to 0 (this is the array counterarray). If we issue a call to e.g. 2 times {do_it;}, the macro times shall set the second element of counterarray to 1 (i.e. counterarray[2] = 1). In C, it is possible to swap index and array name in such an assignment, so we can write 2[counterarray] = 1 to acchieve the same. This is exactly what the macro times does as first step. Then, we can later scan the array counterarray until we find an element that is not 0, but 1. The corresponding index is then the upper iteration bound. It is stored in variable searcher. Since we want to support nesting, we have to store the upper bound for each nesting depth separately, this is done by searchermax[depth]=searcher+1.
  • 检索上迭代界:基本思想是拥有一个chars数组,这些chars最初都设置为0(这是数组反数组)。如果我们发出调用。2 * { do_it;},宏*应当设置counterarray的第二个元素1(即counterarray[2]= 1)。在C语言中,可以互换指数和数组名在这样一个任务,所以我们可以写2[counterarray]= 1人们相同的。这正是宏观时代所做的第一步。然后,我们可以稍后扫描数组反数组,直到找到一个不是0而是1的元素。相应的索引就是上迭代界。它存储在变量搜索器中。由于我们想要支持嵌套,所以我们必须单独存储每个嵌套深度的上限,这是由searchermax[depth]=searcher+1完成的。
  • Adjusting current nesting depth: As said, we want to support nesting of loops, so we have to keep track of the current nesting depth (done in the variable depth). We increment it by one if we start such a loop.
  • 调整当前嵌套深度:如前所述,我们希望支持循环嵌套,因此我们必须跟踪当前嵌套深度(在可变深度中完成)。如果我们开始这样的循环,我们将它增加1。
  • The actual counter variable: We have a "variable" called _ that implicitly gets assigned the current counter. In fact, we store one counter for each nesting depth (all stored in the array counter. Then, _ is just another macro that retrieves the proper counter for the current nesting depth from this array.
  • 实际的计数器变量:我们有一个名为_的“变量”,它隐式地分配当前计数器。实际上,我们为每个嵌套深度存储一个计数器(所有存储在数组计数器中)。然后,_只是另一个宏,它从这个数组中检索当前嵌套深度的适当计数器。
  • The actual for loop: We take the for loop into parts:
    • We initialize the counter for the current nesting depth to 0 (done by counter[depth] = 0).
    • 我们将当前嵌套深度的计数器初始化为0(由counter[depth] = 0完成)。
    • The iteration step is the most complicated part: We have to check if the loop at the current nesting depth has reached its end. If so, we have do update the nesting depth accordingly. If not, we have to increment the current nesting depth's counter by 1. The variable lastloop is 1 if this is the last iteration, otherwise 0, and we adjust the current nesting depth accordingly. The main problem here is that we have to write this as a sequence of expressions, all separated by commata, which requires us to write all these conditions in a very non-straight-forward way.
    • 迭代步骤是最复杂的部分:我们必须检查在当前嵌套深度上的循环是否已经结束。如果是这样,我们将相应地更新嵌套深度。如果没有,我们必须将当前嵌套深度计数器增加1。如果这是最后一次迭代,变量lastloop是1,否则为0,我们相应地调整当前嵌套深度。这里的主要问题是我们必须把它写成一个表达式的序列,所有的表达式都用逗号分开,这就要求我们以非常不直接的方式写出所有的条件。
    • The "increment step" of the for loop consists of only one assignment, that increments the appropriate counter (i.e. the element of counter of the proper nesting depth) and assigns this value to our "counter variable" _.
    • for循环的“增量步骤”只包含一个赋值,该赋值增加适当的计数器(即适当嵌套深度的计数器的元素),并将该值赋给我们的“计数器变量”_。
  • 实际的for循环:我们考虑for循环部分:我们初始化计数器当前嵌套深度为0(由计数器(深度)= 0)。迭代步骤是最复杂的部分:我们必须检查当前的循环嵌套深度已经结束了。如果是这样,我们将相应地更新嵌套深度。如果没有,我们必须将当前嵌套深度计数器增加1。如果这是最后一次迭代,变量lastloop是1,否则为0,我们相应地调整当前嵌套深度。这里的主要问题是我们必须把它写成一个表达式的序列,所有的表达式都用逗号分开,这就要求我们以非常不直接的方式写出所有的条件。for循环的“增量步骤”只包含一个赋值,该赋值增加适当的计数器(即适当嵌套深度的计数器的元素),并将该值赋给我们的“计数器变量”_。

#8


4  

What abelenky said.

abelenky所说的。

And if your { // Do stuff } is multi-line, make it a function, and call that function -- twice.

如果你的{// Do stuff}是多行,使它成为一个函数,并调用那个函数——两次。

#9


3  

Another attempt:

另一个尝试:

for(i=2;i--;) /* Do stuff */

This solution has many benefits:

这个解决方案有很多好处:

  • Shortest form possible, I claim (13 chars)
  • 我要求最短的表格(13个字符)
  • Still, readable
  • 不过,可读
  • Includes initialization
  • 包括初始化
  • The amount of repeats ("2") is visible in the code
  • 重复的数量(“2”)在代码中是可见的
  • Can be used as a toggle (1 or 0) inside the body e.g. for alternation
  • 可以用作在身体内的开关(1或0),例如更换
  • Works with single instruction, instruction body or function call
  • 适用于单指令、指令体或函数调用。
  • Flexible (doesn't have to be used only for "doing twice")
  • 灵活(不必只用于“做两次”)
  • Dijkstra compliant ;-)
  • Dijkstra算法兼容;-)

From comment:

评论:

for (i=2; i--; "Do stuff");

#10


2  

Use function:

使用功能:

func();
func();

Or use macro (not recommended):

或使用宏(不推荐):

#define DO_IT_TWICE(A) A; A

DO_IT_TWICE({ x+=cos(123); func(x); })

#11


2  

If your compiler supports this just put the declaration inside the for statement:

如果您的编译器支持这一点,请将声明放在for语句中:

for (unsigned i = 0; i < 2; ++i)
{
 // Do stuff
}

This is as elegant and efficient as it can be. Modern compilers can do loop unrolling and all that stuff, trust them. If you don't trust them, check the assembler.

这是最优雅和有效的。现代编译器可以做循环展开等等,相信它们。如果您不信任它们,请检查汇编程序。

And it has one little advantage to all other solutions, for everybody it just reads, "do it twice".

它对所有其他的解决方案都有一个小优势,对每个人来说,它只是写着“做两次”。

#12


2  

Many people suggest writing out the code twice, which is fine if the code is short. There is, however, a size of code block which would be awkward to copy but is not large enough to merit its own function (especially if that function would need an excessive number of parameters). My own normal idiom to run a loop 'n' times is

许多人建议把代码写两次,如果代码很短,这是可以的。但是,有一个代码块的大小是难以复制的,但是它的大小并不能满足其本身的功能(特别是当该函数需要过多的参数时)。我自己循环n次的习惯用法是

  i = number_of_reps;
  do
  {
    ... whatever
  } while(--i);

In some measure because I'm frequently coding for an embedded system where the up-counting loop is often inefficient enough to matter, and in some measure because it's easy to see the number of repetitions. Running things twice is a bit awkward because the most efficient coding on my target system

在某种程度上,因为我经常为一个嵌入式系统编写代码,在这个系统中,向上计数循环的效率非常低,这很重要,在某种程度上,因为它很容易看到重复的次数。两次运行东西有点尴尬,因为目标系统上最高效的编码

  bit rep_flag;

  rep_flag = 0;
  do
  {
    ...
  } while(rep_flag ^= 1); /* Note: if loop runs to completion, leaves rep_flag clear */

doesn't read terribly well. Using a numeric counter suggests the number of reps can be varied arbitrarily, which in many instances won't be the case. Still, a numeric counter is probably the best bet.

并没有很好的阅读。使用数字计数器表明,代表的数量可以任意变化,在许多情况下不是这样的。不过,数字计数器可能是最好的选择。

#13


2  

Assuming C++0x lambda support:

假设c++ 0 xλ支持:

template <typename T> void twice(T t)
{
    t();
    t();
}

twice([](){ /*insert code here*/ });

Or:

或者:

twice([]()
{ 
    /*insert code here*/ 
});

Which doesn't help you since you wanted it for C.

这对你没有帮助,因为你想要C。

#14


2  

As Edsger W. Dijkstra himself put it : "two or more, use a for". No need to be any simpler.

正如Edsger W. Dijkstra自己所言:“两个或更多,使用a for”。没有必要再简单了。

#15


1  

Good rule: three or more, do a for.

好的规则:三个或更多,做a for。

I think I read that in Code Complete, but I could be wrong. So in your case you don't need a for loop.

我想我在《代码完成》中读到过,但我可能错了。在你的例子中,你不需要一个for循环。

#16


1  

This is the shortest possible without preprocessor/template/duplication tricks:

这是没有预处理器/模板/复制技巧的最短时间:

for(int i=2; i--; ) /*do stuff*/;

Note that the decrement happens once right at the beginning, which is why this will loop precisely twice with the indices 1 and 0 as requested.

注意,减量在一开始就发生了一次,这就是为什么它会按照要求对索引1和0进行两次精确的循环。

Alternatively you can write

或者你可以写

for(int i=2; i--; /*do stuff*/) ;

But that's purely a difference of taste.

但这纯粹是口味的不同。

#17


0  

If what you are doing is somewhat complicated wrap it in a function and call that function twice? (This depends on how many local variables your do stuff code relies on).

如果你所做的是有点复杂的将它封装到一个函数中并调用该函数两次?(这取决于do代码所依赖的本地变量的数量)。

You could do something like

你可以这样做

void do_stuff(int i){
    // do stuff
}

do_stuff(0);
do_stuff(1);

But this may get extremely ugly if you are working on a whole bunch of local variables.

但是如果你研究大量的局部变量,这可能会变得非常糟糕。

#18


0  

//dostuff
  stuff;
//dostuff (Attention I am doing the same stuff for the :**2nd** time)
  stuff;

#19


0  

First, use a comment

首先,使用一个评论

/* Do the following stuff twice */

then,
1) use the for loop
2) write the statement twice, or
3) write a function and call the function twice
do not use macros, as earlier stated, macros are evil.

然后,1)使用for循环2)将语句写两次,或者3)写一个函数,并调用函数两次不使用宏,如前所述,宏是邪恶的。

(My answer's almost a triangle)

(我的答案几乎是一个三角形)

#20


0  

What is elegance? How do you measure it? Is someone paying you to be elegant? If so how do they determine the dollar-to-elegance conversion?

什么是优雅?你如何衡量它?有人付钱让你优雅吗?如果是这样,他们如何确定美元对优雅的转换?

When I ask myself, "how should this be written," I consider the priorities of the person paying me. If I'm being paid to write fast code, control-c, control-v, done. If I'm being paid to write code fast, well.. same thing. If I'm being paid to write code that occupies the smallest amount of space on the screen, I short the stock of my employer.

当我问自己,“这应该怎么写”时,我考虑了支付给我的人的优先顺序。如果我被雇来写快速代码,control-c, control-v,完成。如果我被雇来写代码快的话。同样的事情。如果有人付钱让我写代码,让我在屏幕上占据最小的空间,我就会做空雇主的股票。

#21


0  

jump instruction is pretty slow,so if you write the lines one after the other,it would work faster,than writing a loop. but modern compilers are very,very smart and the optimizations are great (if they are allowed,of course). if you have turned on your compiler's optimizations,you don't care the way,you write it - with loop or not (:

跳转指令非常慢,所以如果你一个接一个地写行,它的工作速度会比写一个循环快。但现代编译器非常非常聪明,优化也很棒(当然,如果允许的话)。如果你已经打开了编译器的优化,你不关心怎么写,你可以用循环来写(

EDIT : http://en.wikipedia.org/wiki/compiler_optimizations just take a look (:

编辑:http://en.wikipedia.org/wiki/compile er_optimization ations看看(:

#22


0  

Close to your example, elegant and efficient:

接近你的例子,优雅而高效:

for (i = 2; i; --i)
{
    /* Do stuff */
}

Here's why I'd recommend that approach:

以下是我推荐这种方法的原因:

  • It initializes the iterator to the number of iterations, which makes intuitive sense.
  • 它初始化迭代器到迭代的次数,这很直观。
  • It uses decrement over increment so that the loop test expression is a comparison to zero (the "i;" can be interpreted as "is i true?" which in C means "is i non-zero"), which may optimize better on certain architectures.
  • 它使用递减而不是递增,因此循环测试表达式是与零的比较(“i;”可以被解释为“我是真的吗?”,在C中表示“我是非零的”),这可以更好地优化某些体系结构。
  • It uses pre-decrement as opposed to post-decrement in the counting expression for the same reason (may optimize better).
  • 它在计数表达式中使用预减量而不是后减量,原因是相同的(可以优化得更好)。
  • It uses a for loop instead of do/while or goto or XOR or switch or macro or any other trick approach because readability and maintainability are more elegant and important than clever hacks.
  • 它使用for循环,而不是do/while、goto、XOR、switch、macro或任何其他技巧方法,因为可读性和可维护性比聪明的黑客更优雅、更重要。
  • It doesn't require you to duplicate the code for "Do stuff" so that you can avoid a loop. Duplicated code is an abomination and a maintenance nightmare.
  • 它不需要您为“Do stuff”复制代码,以便您可以避免循环。重复的代码是令人厌恶的,也是维护的梦魇。

If "Do stuff" is lengthy, move it into a function and give the compiler permission to inline it if beneficial. Then call the function from within the for loop.

如果“Do stuff”很长,那么将它移动到函数中,并给编译器以内联的权限。然后调用for循环中的函数。

#23


-1  

void loopTwice (bool first = true)
{
    // Recursion is your friend
    if (first) {loopTwice(false);}

    // Do Stuff
    ...
}

I'm sure there's a more elegant way, but this is simple to read, and pretty simply to write. There might even be a way to eliminate the bool parameter, but this is what I came up with in 20 seconds.

我肯定有一种更优雅的方式,但这很容易读,写起来也很简单。甚至可能有一种方法可以消除bool参数,但这就是我在20秒内得出的结果。