很多时候我需要在for循环中做两件事。简单地说,我可以使用迭代器设置for循环并进行两次:
for (i = 0; i < 2; i++)
{
// Do stuff
}
现在我有兴趣尽可能简单地做这个,也许没有初始化器或迭代器?有没有其他的,非常简单和优雅的方法来实现这个目标?
答案 0 :(得分:59)
这很优雅,因为它看起来像一个三角形;和三角形都很优雅。
i = 0;
here: dostuff();
i++; if ( i == 1 ) goto here;
答案 1 :(得分:35)
将其封装在一个函数中并调用它两次。
void do_stuff() {
// Do Stuff
}
// .....
do_stuff();
do_stuff();
注意:如果在 stuff 逻辑中使用封闭函数的变量或参数,则可以将它们作为参数传递给extracted {{1功能。
答案 2 :(得分:30)
如果它只有两次,并且你想避免循环,只需写两次darn的东西。
statement1;
statement1; // (again)
答案 3 :(得分:16)
如果循环对你来说过于冗长,你也可以为它定义一个别名:
#define TWICE for (int _index = 0; _index < 2; _index++)
这会导致代码:
TWICE {
// Do Stuff
}
// or
TWICE
func();
我只建议使用这个宏,如果你必须经常这样做,我认为普通的for循环更具可读性。
答案 4 :(得分:9)
答案 5 :(得分:8)
因此,经过一段时间后,这里有一种方法可以让您在纯C中编写以下内容:
2 times {
do_something()
}
您必须将this little thing包含为简单的头文件(我总是将文件称为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;
}
_
的变量(简单的下划线)中。_A
的大小在头文件中进行调整。_Y
来调整。您可以看到full (=de-obfuscated) source-code here。假设我们想要允许多达18个循环。
char
的数组,这些数组最初都设置为0(这是数组counterarray
)。如果我们发出呼叫,例如2 times {do_it;}
,宏 times
应将counterarray
的第二个元素设置为1
(即counterarray[2] = 1
)。在C中,可以在这样的赋值中交换索引和数组名称,因此我们可以编写2[counterarray] = 1
来实现相同的操作。这正是宏times
作为第一步所做的事情。然后,我们可以稍后扫描数组counterarray
,直到我们找到一个不为0的元素,但是1.相应的索引就是上面的迭代边界。它存储在变量searcher
中。由于我们要支持嵌套,我们必须分别为每个嵌套深度存储上限,这由searchermax[depth]=searcher+1
完成。depth
中完成)。如果我们开始这样的循环,我们将它增加一。_
的“变量”,它隐式地被赋予当前计数器。实际上,我们为每个嵌套深度存储一个计数器(全部存储在数组counter
中。)然后,_
只是另一个宏,它从该数组中检索当前嵌套深度的正确计数器。counter[depth] = 0
完成)。lastloop
为1,否则为0,我们相应地调整当前嵌套深度。这里的主要问题是我们必须将它写成一个表达式序列,所有表达式都用逗号分隔,这要求我们以非常直接的方式编写所有这些条件。counter
的元素)并将此值赋给我们的“计数器变量”{ {1}}。答案 6 :(得分:4)
abelenky说的是什么。
如果您的{ // Do stuff }
是多行的,请将其设为函数,并调用该函数 - 两次。
答案 7 :(得分:3)
这个怎么样?
void DostuffFunction(){}
for (unsigned i = 0; i < 2; ++i, DostuffFunction());
此致 巴勃罗。
答案 8 :(得分:3)
另一次尝试:
for(i=2;i--;) /* Do stuff */
此解决方案有许多好处:
来自评论:
for (i=2; i--; "Do stuff");
答案 9 :(得分:2)
假设C ++ 0x lambda支持:
template <typename T> void twice(T t)
{
t();
t();
}
twice([](){ /*insert code here*/ });
或者:
twice([]()
{
/*insert code here*/
});
由于你想要C语言,这对你没有帮助。
答案 10 :(得分:2)
很多人建议两次写出代码,如果代码很短,这很好。但是,有一个代码块的大小,复制起来不方便,但不足以值得它自己的功能(特别是如果该功能需要过多的参数)。我自己正常运行循环'n'次的习惯是
i = number_of_reps; do { ... whatever } while(--i);
在某种程度上,因为我经常为嵌入式系统编码,其中向上计数循环通常效率低下,并且在某种程度上因为很容易看到重复次数。两次运行有点尴尬,因为我的目标系统上最有效的编码
bit rep_flag; rep_flag = 0; do { ... } while(rep_flag ^= 1); /* Note: if loop runs to completion, leaves rep_flag clear */
读得不太好。使用数字计数器表明,reps的数量可以任意改变,在许多情况下不是这种情况。不过,数字计数器可能是最好的选择。
答案 11 :(得分:2)
正如Edsger W. Dijkstra自己说的那样:“两个或更多,使用一个”。不需要更简单。
答案 12 :(得分:2)
如果你的编译器支持这个,只需将声明放在for
语句中:
for (unsigned i = 0; i < 2; ++i)
{
// Do stuff
}
这是优雅和高效的。现代编译器可以进行循环展开和所有这些东西,相信它们。如果您不信任它们,请检查汇编程序。
它对所有其他解决方案都有一点点优势,对于它所读取的每个人来说,“做两次”。
答案 13 :(得分:2)
使用功能:
func();
func();
或使用宏(不推荐):
#define DO_IT_TWICE(A) A; A
DO_IT_TWICE({ x+=cos(123); func(x); })
答案 14 :(得分:1)
如果没有预处理器/模板/复制技巧,这是最短的:
for(int i=2; i--; ) /*do stuff*/;
请注意,减量在开头就发生了一次,这就是为什么这将按照请求使用索引1
和0
精确循环两次。
或者你可以写
for(int i=2; i--; /*do stuff*/) ;
但这纯粹是品味的差异。
答案 15 :(得分:1)
好规则:三个或更多,
我想我在Code Complete中读到了这一点,但我可能错了。因此,在您的情况下,您不需要for循环。
答案 16 :(得分:0)
贴近你的榜样,优雅高效:
for (i = 2; i; --i)
{
/* Do stuff */
}
这就是我推荐这种方法的原因:
如果“Do stuff”很长,请将其移动到函数中,并授予编译器内联权限,如果有益的话。然后从for循环中调用该函数。
答案 17 :(得分:0)
我喜欢Chris Case的解决方案(在此处),但是C语言没有默认参数。
我的解决方案:
bool cy = false;
do {
// Do stuff twice
} while (cy = !cy);
如果需要,可以通过检查布尔变量(可能是三元运算符)在两个循环中做不同的事情。
答案 18 :(得分:0)
什么是优雅?你怎么测量它?有人付钱给你优雅吗?如果是这样,他们如何确定从美元到优雅的转换?
当我问自己时,“应该怎么写”,我考虑付钱给我的人的优先事项。如果我付钱写快速代码,control-c,control-v,就完成了。如果我付钱快速编写代码,那么......同样的事情。如果我付费编写代码占据屏幕上最小的空间,我会缩短雇主的存量。
答案 19 :(得分:0)
首先,使用评论
/* Do the following stuff twice */
然后,
1)使用for循环
2)写两次声明,或者
3)写一个函数并调用该函数两次
不要使用宏,如前所述,宏是邪恶的。
(我的答案几乎是一个三角形)
答案 20 :(得分:0)
//dostuff
stuff;
//dostuff (Attention I am doing the same stuff for the :**2nd** time)
stuff;
答案 21 :(得分:0)
跳转指令非常慢,所以如果你一个接一个地写行,它会比写一个循环更快。但现代编译器非常非常智能,优化程度很高(当然,如果允许的话)。如果你打开了编译器的优化,你就不在乎了,你写它 - 用循环或不用(:
编辑:http://en.wikipedia.org/wiki/compiler_optimizations只需看看(:
答案 22 :(得分:0)
如果您正在做的事情有点复杂,请将其包装在函数中并调用该函数两次? (这取决于do stuff
代码依赖的局部变量数量。)
您可以执行类似
的操作void do_stuff(int i){
// do stuff
}
do_stuff(0);
do_stuff(1);
但如果你正在研究一大堆局部变量,这可能会变得非常难看。
答案 23 :(得分:-1)
void loopTwice (bool first = true)
{
// Recursion is your friend
if (first) {loopTwice(false);}
// Do Stuff
...
}
我确信这是一种更优雅的方式,但这很容易阅读,而且非常简单。甚至可能有一种消除bool参数的方法,但这是我在20秒内提出的。