2012-01-31 165 views
2

这可能是一个奇怪的问题,但是如何很好地循环一个类型的所有值。特别是标准积分类型,如unsigned short。正常的for循环结构呈现一个难点:用什么条件来退出循环 - 因为所有的值都是有效的。循环遍历所有值

当然,有几种方法可以完成工作。退出最后一个值,然后在循环后处理。使用更大的int来计数。问题是,有没有更优雅的方式?

+0

听起来像你试图蛮力的东西?不要尝试使用64位整数,尽管... – Mysticial 2012-01-31 23:12:44

回答

2

如果你想要一个漂亮的解决方案,你可以这样做:

for(auto x : everyvalue<short>()) { 
    std::cout << x << '\n'; 
} 

其中everyvalue是:

#include <limits> 
template<typename T> 
struct everyvalue { 
    struct iter { 
    T x; 
    bool flag; 
    inline iter operator++() { 
     if(x == std::numeric_limits<T>::max()) 
     flag = true; 
     else 
     ++x; 
     return *this; 
    } 
    inline T operator*() { return x;} 
    inline bool operator!=(iter& i) {return flag != i.flag;} 
    // note: missing some iterator requirements, still should work 
    }; 
    inline iter begin() { return iter{std::numeric_limits<T>::min(),0}; } 
    inline iter end() { return iter{std::numeric_limits<T>::max(),1}; } 
}; 

否则简单break将是首选。

+1

我要给这个答案一个大绿色的勾号。最终结果是优雅和广泛的。所有丑陋的东西都是一次完成,完成并隐藏起来,这是如何使用C++的重要组成部分(在我看来)。其他一些答案可能会有性能优势,但这并不是我之前的做法。 – wxffles 2012-02-01 20:46:33

0

你可以只用一个更大的类型:

unsigned long i; 
for (i = std::numeric_limits<unsigned short>::min(); 
    i <= std::numeric_limits<unsigned short>::max(); 
    i++) 
+0

'我<= i!= [']'?那只是为了'我<= [']'? – quasiverse 2012-01-31 23:16:17

+0

是 - 复制/粘贴错误!固定。 – 2012-01-31 23:17:02

+1

+1当然,假设'unsigned long'确实比'unsigned short'大。这是我知道的实现,但我只是指出它不能保证。 – 2012-01-31 23:17:44

3
#include <limits> 
int i = std::numeric_limits<int>::min(); 
do { 
    ... 
    if(i == std::numeric_limits<int>::max()) 
     break; 
    i++; 
} while(true); 

这是相反的,转化为为()语句:

#include <limits> 
int i = std::numeric_limits<int>::min(); 
while(true) { 
    if(i == std::numeric_limits<int>::max()) 
     break; 
    ... 
    i++; 
}; 
+2

我不downvoting,但有符号整数溢出是未定义的行为。 (有关有符号整数溢出出错的示例,请参阅http://stackoverflow.com/q/7682477) – 2012-01-31 23:19:37

+0

编辑出来并不是什么大问题 – 2012-01-31 23:20:56

3

我担心关于这个同样的问题一次,这是我能想到的最好的:

unsigned char c = 0; 
do 
{ 
    printf("%d ", (int)c); //or whatever 
} while (++c != 0); 

我发现do..while语法很有用的极少数情况之一。

请注意,从技术上讲,它只对无符号类型有效,因为我依赖于值的包装。

0

我最近问了一个关于bools的问题:How to write a `for` loop over bool values (false and true)。你可以在那里寻找答案。然后我意识到,因为for循环遍历所有可能的值需要再次评估条件,所以需要额外的值(以任何形式 - 更大类型,第二个变量等)来正确区分所有情况。而且,do-while循环适用于这种情况,因为它需要完全一样多的比较,因为有不同的值。

1

你可以通过你用标志递增值结合起来,说你已经达到最大,所以你不增加过去吧:

for (char i (std::numeric_limits<char>::min()), j (1); 
     i != std::numeric_limits<char>::max() || j--; 
     i += j) 
    std::cout << (int) i << '\n'; 

但只有优雅如“复杂”,而不是'干净简单的线条'。