2013-10-25 39 views
5

我的代码中有一个block,for循环应该根据条件向前或向后运行。什么是有条件地控制for循环方向的最好方法

if (forwards) { 
    for (unsigned x = 0; x < something.size(); x++) { 
     // Lots of code 
    } 

} else { 
    for (unsigned x = something.size()-1 ; x >= 0 ; x--) { 
     // Lots of code 
    } 
} 

有没有一种很好的方法来设置它,所以我不重复for循环中的所有代码两次?

问题中的'东西'是std :: vector <>,所以也许它可能与迭代器? (我没有使用C++ 11)

+1

反向迭代器。 – yngccc

+0

使用while或do-while循环 –

+0

请记住,在第二个for循环中'x> = 0'因为x是无符号的,所以它总是会计算真实值。 – doug

回答

6

您分开的循环中使用的值循环值:

for (unsigned x2 = 0; x2 < something.size(); x2++) { 
    const int x = forward ? x2 : (something.size()-1) - x2; 
    // Lots of code using x 
} 
+0

我选择这个答案作为a)我用它和b)它最直接地解决了我提出的问题。我也喜欢其他答案。许多方法去皮肤猫! – joeButler

+0

您已经将条件从循环外部移至内部 - 功能强大,但如果这是性能至关重要的代码,则肯定不是最佳选择。另一方面,既然你说了“很多代码”,那么条件不会增加很大的负担......而分支预测会对你有利。 –

+0

是的,我同意这一点。但我想总会有条件的评估或函数调用。在我的“真实”代码中,有一个内部循环正在进行繁重的工作,所以我很乐意随时随地使用绝大多数时间。 – joeButler

6

也许最简单的方法就是Lots of code转化为函数的参数x

void do_lots_of_stuff(unsigned x) { 
    // Lots of code 
} 

//////// 

if (forwards) { 
    for (unsigned x = 0; x < something.size(); x++) { 
    do_lots_of_stuff(x); 
    } 
} else { 
    for (unsigned x = something.size()-1 ; x >= 0 ; x--) { 
    do_lots_of_stuff(x); 
    } 
} 
+0

请解决这个问题:'for(unsigned x = something.size() - 1; x> = 0; x--){'因为它会运行一个无限循环。 S/B'for(int x = something.size() - 1; x> = 0; x--){' – doug

2
template<typename Cont, typename Func> 
Func directional_for_each(Cont c, bool forwards, Func f) { 
    return forwards ? for_each(begin(c), end(c), f) : for_each(rbegin(c), rend(c), f); 
} 

像这样来使用:与该函数的调用,同时替换循环体

vector<int> v; 
// put stuff in v... 
bool forwards = false; 
directional_for_each(v, forwards, [](decltype(v[0]) x) { 
    // Lots of code using x 
}); 

由于您没有使用C++ 11,所以包含'使用x的许多代码'的lambda必须用其他地方定义的函数替换。

3

或者你也可以做这样的事情:

for (unsigned x = (forward ? 0: something.size()); x != (forward ? something.size() :0); forward? x++: x--) { 
    // Lots of code 
} 

编译器将最有可能对其进行优化和评估forward只有一次,因为它的价值在for循环我认为不会改变。

0

我只是碰巧遇到了这个问题,并认为我可能会提供一个解决方案,无需有条件地检查每个循环是否前进或后退。

// Could do 0xFFFFFFFFU if unsigned is 32bits. 
const unsigned MAX_UINT = 0U - 1U; 

// Will need this later. 
const bool backwards = !forwards; 

// temp is either going to be one or zero. 
const unsigned temp = unsigned(forwards); 

// By adding it to all ones, if temp is ones the mask is all zeros 
// else if temp is zero we get all ones. 
const unsigned mask = temp + MAX_UINT; 

// Bit shift temp over such that it will push all of the ones after 
// the first bit to all zeros if temp is one. This means we will 
// either have a one or a negative one if temp is zero. 
const int delta = int((temp << 1) + MAX_UINT); 

const int size = something.size(); 

// The mask will be zero if forwards is true therein i will start out 
// at zero else the mask will be all ones therein return (size - 1). 
for(int i = int((size - 1) & mask); 
// This may be a more complicated check, but there is only one conditional branch. 
    (forwards && (i < size)) || (backwards (0 <= i)); 
    i += delta) 
{ 
    // Lots of code 
} 
相关问题