假设我有两个无符号整数:
size_t A, B;
Run Code Online (Sandbox Code Playgroud)
它们加载了一些随机数,A可能比B大,等于或小.我想从A循环到B.但是,比较和增量都取决于哪个更大.
for (size_t i = A; i <= B; ++i) //A <= B
for (size_t i = A; i >= B; --i) //A >= B
Run Code Online (Sandbox Code Playgroud)
显而易见的蛮力解决方案是将这些嵌入if语句中:
if (A <= B)
{
for (size_t i = A; i <= B; ++i) ...
}
else
{
for (size_t i = A; i >= B; --i) ...
}
Run Code Online (Sandbox Code Playgroud)
请注意,我必须从 A 循环到 B,所以我不能有两个中间整数,并将A和B放入右侧插槽,然后进行相同的比较和增量.在"A更大"的情况下,我必须减少,而相反的必须增加.
我将要有许多嵌套循环,需要相同的设置,这意味着每个if/else都会有一个函数调用,我必须传递大量的变量,或者另一个if/else与另一个if/else等.
在不牺牲速度的情况下避免这种情况有什么棘手的捷径吗?功能指针和东西在一个紧凑的,经常重复的循环中听起来非常痛苦.有一些疯狂的模板解决方案吗?
我的错误,最初是误解了这个问题.
为了使一个包容性的循环,从A到B,你有一个棘手的情况.你需要循环过去 B.所以你在循环之前计算出这个值.我在for循环中使用了逗号运算符,但为了清晰起见,你总是可以把它放在外面.
int direction = (A < B) ? 1 : -1;
for( size_t i = A, iEnd = B+direction; i != iEnd; i += direction ) {
...
}
Run Code Online (Sandbox Code Playgroud)
如果你不介意修改A和B,你可以改为(A用作循环变量):
for( B+=direction, A != B; A += direction ) {
}
Run Code Online (Sandbox Code Playgroud)
我玩了一下......当涉及到函数指针时,不知道内联规则是什么,或者这是否更快,但它无论如何都是一个练习.=)
inline const size_t up( size_t& val ) { return val++; }
inline const size_t down( size_t& val ) { return val--; }
typedef const size_t (*FnIncDec)( size_t& );
inline FnIncDec up_or_down( size_t A, size_t B )
{
return (A <= B) ? up : down;
}
int main( void )
{
size_t A = 4, B = 1;
FnIncDec next = up_or_down( A, B );
for( next(B); A != B; next(A) ) {
std::cout << A << endl;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
对此:
这对于A = 0,B = UINT_MAX(反之亦然)的情况不起作用
那是正确的.问题是由于溢出而导致的初始值i和iEnd变为相同.要处理它,你可以使用do->while循环.这将删除初始测试,这是多余的,因为您将始终至少执行一次循环体...通过删除第一个测试,您第一次迭代超过终止条件.
size_t i = A;
size_t iEnd = B+direction;
do {
// ...
i += direction;
} while( i != iEnd );
Run Code Online (Sandbox Code Playgroud)
size_t const delta = size_t(A < B? 1 : -1);
size_t i = A;
for( ;; )
{
// blah
if( i == B ) { break; }
i += delta;
}
Run Code Online (Sandbox Code Playgroud)