2012-01-31 162 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'; 

但只有優雅如「複雜」,而不是'乾淨簡單的線條'。