2016-03-26 7 views
3

整数の可能なすべての値を繰り返したいと思っています。終了条件が偽になることはありませんので、このコードは動作しません:符号なし整数のすべての値を反復する最も簡単な方法

for (uint32_t i = 0; i <= 0xFFFFFFFF; i++) 
    std::cout << i << std::endl; 

私はこれを作ってみた:

auto loopBody = [](uint32_t value) 
{ 
    std::cout << value << std::endl; 
}; 

uint32_t last = 0xFFFFFFFF; 
for (uint32_t i = 0; i < last; i++) 
    loopBody(i); 

loopBody(last); 

それはしかし、かなり醜いです。これを行うにはもっときれいな方法がありますか?

+0

を使用することを意味しているたぶん、あなたは0x100000000' 'に' int64_t'インデックスとループを使用することができます?、ループの終わりに条件テストのために呼び出しますか – zneak

+0

'std :: numeric_limits :: max()'を使用してください。符号付き整数のオーバーフローは未定義の動作であることに注意してください。 – kec

+0

「可愛さ」は任意です。私はちょうどループを持っていると思うし、余分なstd :: cout文はそれを行う関数を定義するよりもきれいです。それがあまりにもバグがあるなら、オーバーフローしないより大きなデータ型を使用するというzneakの提案を使用してください。次に、大きなデータ型をループする必要がある場合、同じ問題が発生します。 –

答えて

1

ループヘッダーでブレーク条件を確認することはできません。これは、最大値を除外する必要があるためです。

代わりに、ループ本体内のチェックを行うと、空のヘッダにチェックを残す:

for (auto i = std::numeric_limits<int>::lowest(); ; ++i) { 
    std::cout << i << '\n'; 
    if (i == std::numeric_limits<int>::max()) 
     break; 
} 

DO-whileループを使用すると、ループ本体の中身をチェックする必要がありますが、あなたはありません外側のスコープにカウンタ変数を移動する必要がある、とあなたは未定義の動作を避けたい場合は、あなただけの符号なし整数型を使用することができます。i++がオーバーフローすること

auto i = std::numeric_limits<unsigned>::lowest(); 
do { 
    std::cout << i << '\n'; 
} while (i++ < std::numeric_limits<unsigned>::max()); 

注意、しかし、それは唯一の後の交流を起こりますしかし、符号付き整数の場合、このオーバーフローは未定義のビヘイビアとなります。たとえオーバーフローが発生した後でも値を使用していなくても、未定義のビヘイビアは予期せぬ結果になる可能性があります。実際に発生しました。

+0

これは実際に私が探していたものです:チェックは、前。すばらしいです! – Sunius

+6

2016年以来 'do {} whie()'を再開しました。 –

+0

@NikosCはまだチェックを行う必要がありますか?どうして? –

0

私はstd::numeric_limitsを使用しますが、それはあなたの意図を最もよく表しています。

int lowest = std::numeric_limits<int>::lowest(); 
int max = std::numeric_limits<int>::max(); 
for (int i = lowest; i < max; ++i) 
    cout << i << '\n'; 
cout << max << '\n'; 

または機能のこのDemo

#include <iostream> 
#include <limits> 
#include <functional> 

template <class T> 
void for_all(std::function<void(T)> fn) 
{ 
    T lowest = std::numeric_limits<T>::lowest(); 
    T max = std::numeric_limits<T>::max(); 
    for (T i{lowest}; i < max; ++i) 
     fn(i); 
    fn(max); 
} 

int main() 
{ 
    for_all<int>([](int i) { 
     std::cout << i << std::endl; 
    }); 
} 

編集を参照してください。コメントを参照してください:私は比較

編集2を編集しました。小道具をkec ;-)

+0

この結果は、私の最初のコード例と同義の生成コードであり、結果として無限ループになります。そのコードは壊れています。 – Sunius

+0

署名付きタイプの場合、これは未定義の動作を呼び出します。しかし、それを '<'に変更し、もう一つ増分を加えてください。 – kec

+0

真。答えを削除しますか? – Maikel

4

私はこのようなものを使用します。

uint32_t i = 0; 
do 
{ 
    // Your code here. 
    i++; 
} 
while (i != 0); 

私は個人的にstd::numeric_limitsを含むソリューションよりも、それはよりエレガント見つけます。


@NicosCは、 signedの整数で、同じトリックをしないでください。これは、符号付きオーバーフローが未定義の動作であるためです。

+3

これは符号付き整数のUBです。しかし、それは無署名で問題ありません。 –

1

まあ、それはdo {} while()

#include <limits> 
#include <iostream> 

int main() { 
    auto beg = std::numeric_limits<unsigned>::lowest(); 
    auto end = std::numeric_limits<unsigned>::max(); 

    std::cout << beg << " " << end << std::endl; 

    long long count = 0LL; 

    auto i = beg; 
    do { 
     ++count; 
     if ((count % (1024LL*1024LL)) == 0) 
      std::cout << count << std::endl; 
    } while(i++ != end); 
    std::cout << count << std::endl; 

    return 0; 
} 
関連する問題