2011-03-28 124 views
25

我希望for循環中的迭代器變量作爲unsigned int反覆迭代爲0,我想不出與i > -1類似的比較,就像它是signed int那樣。unsigned int反向迭代for循環

for (unsigned int i = 10; i <= 10; --i) { ... } 

但這似乎很清楚,因爲它是依靠無符號整數的數值溢出至超過10

也許我只是沒有一個清醒的頭腦,但什麼更好的辦法要做到這一點...

免責聲明:這只是一個簡單的使用情況下,10的上限是微不足道的,它可以是任何東西,並且i必須是unsigned int

+0

如果我最初等於0呢? – 2011-03-28 11:22:11

+0

我認爲這是做到這一點的方法。當C++引入size_t時,它讓我非常惱火,但我已經習慣了。 – 2011-03-28 11:22:57

+0

然後i = 0;我<= 0;它按預期迭代一次... – dcousens 2011-03-28 11:23:03

回答

22

您可以使用

for (unsigned int j = n; j-- > 0;) {} 

它重複從n-1下降到0

+0

這種方法有侷限性,所以我按照Alexandre C.的建議去做。 – 2014-03-14 08:08:23

+0

不錯的解決方案,但我不得不承認,我覺得這有點難以閱讀。 – TobiMcNamobi 2014-11-06 09:59:07

+0

@AnupamSrivastava有什麼限制? – Yankee 2017-09-14 06:49:33

11

下你想要做什麼:

for (unsigned i = 10; i != static_cast<unsigned>(-1); --i) 
{ 
    // ... 
} 

完美定義和實際工作。標準類型的算術由標準精確定義。事實上:

4.7/2(關於澆鑄到一個無符號型):

如果目標類型是無符號的,所得到的值是至少無符號整數全等到源整數(模2^n,其中n是用於表示無符號類型)

3.9.1/4

比特的數目個

無符號整數,聲明未簽名,應當服從算術模的法律2^n,其中n是位在整數的特定大小的值表示

+0

無符號變量不能小於0,我不希望每次都有編譯器警告... – dcousens 2011-03-28 11:24:07

+0

我通常會在劇集中使用它。或者我只是在這種情況下使用int。 – 2011-03-28 11:25:03

+0

爲什麼downvote? 4.7/2在這一點上似乎很清楚,代碼的行爲是完美定義的,並按照你的意願行事。 – 2011-03-28 11:27:44

1

我會用兩個變量的數量:

unsigned int start = 10; 
for (unsigned int j = 0, i = start; j <= start; ++ j, -- i) { 
    // ... 
} 

您也可以使用while循環:

unsigned int start = 10; 
unsigned int i = start + 1; 
while (i --) { 
    // ... 
} 
+0

這是我想要避免的,但可能是考慮到環境的最明顯的解決方案。 – dcousens 2011-03-28 11:29:09

+0

爲什麼使用2個變量,如果1是完全不夠的?對我來說,沒有可讀性優勢。第二個循環很好(除了迭代器索引作用域超出循環塊外,其餘大部分與我的相同)。 – 2011-03-29 09:02:41

+0

因爲我更喜歡第二個版本(我在編寫第一個版本時總是犯錯誤),但有些人覺得難以理解。 – 2011-03-29 09:17:01

1
for(unsigned i = x ; i != 0 ; i--){ ... 

而且如果你想在i == 0時執行循環體,並在那之後停止。剛開始i = x+1;

順便說一句,爲什麼我必須是無符號的?

1

我能想到的兩種選擇要麼投或者是燒焦的數字(可以做隱式地比較-1,例如),或使用循環條件來檢查溢出這樣的:

for(unsigned i=10;i>i-1;--i){ } // i = 10, 9, ... , 1 
for(unsigned i=10;i+1>i;--i){ } // i = 10, 9, ... , 1,0 

這循環將繼續下去,直到我溢出(意味着它達到零)。請注意,我重複迭代1,否則可能會以無限循環結束。

+2

我最初用於(無符號i = 10; i + 1> 0; - i){...},但它似乎有點不清楚......猜測它不是一個簡單的解決方案:P。 – dcousens 2011-03-28 11:40:47

3

我對這種模式通常是...

for(unsigned int i_plus_one = n; i_plus_one > 0; --i_plus_one) 
{ 
    const unsigned int i = i_plus_one - 1; 
    // ... 
} 
2

你真的從一些數字比std::numeric_limits<int>::max()更大的迭代下來?如果沒有,我實際上建議只使用一個普通的int作爲你的循環變量,而static_cast它會在你的代碼中的unsigned中被期望它爲無符號的地方。通過這種方式,您可以使用直觀的>= 0> -1條件,並且一般而言,我會期望它比任何未簽名的替代方案更具可讀性。

static_cast只是告訴編譯器如何操作變量,並且根本沒有性能影響。

+0

你有沒有任何證據證明這裏沒有真正演員演員?這是有道理的,但我只想確定一下。也就是說,因爲我要儘可能快地抽數字,而這裏的演員陣容並不重要,如果存在其他(非演員)方法,我不明白爲什麼我應該這樣做。 – dcousens 2011-03-28 13:51:34

+0

我喜歡實用的方法。和可讀性。 +1 – TobiMcNamobi 2014-11-06 10:08:30

0

剛:

int start = 10; 
for(unsigned int iPlus1 = start + 1 ; iPlus1 > 0 ; iPlus1--) { 
    // use iPlus1 - 1 if you need (say) an array index 
    a[iPlus1 - 1] = 123; // ... 
} 

沒有?

0

您可以嘗試並定義下面的宏:

#define for_range(_type, _param, _A1, _B1) \ 
    for (_type _param = _A1, _finish = _B1,\ 
    _step = static_cast<_type>(2*(((int)_finish)>(int)_param)-1),\ 
    _stop = static_cast<_type>(((int)_finish)+(int)_step); _param != _stop; \ 
_param = static_cast<_type>(((int)_param)+(int)_step)) 

現在你可以使用它:

for_range (unsigned, i, 10,0) 
{ 
    cout << "backwards i: " << i << endl; 
} 

它可用於通過無符號整數,枚舉和字符向後和向前遍歷:

for_range (char, c, 'z','a') 
{ 
    cout << c << endl; 
} 

enum Count { zero, one, two, three }; 

for_range (Count, c, zero, three) 
{ 
    cout << "forward: " << c << endl; 
} 

儘管它的定義很尷尬,但它的優化非常好。我在VC++中查看反彙編程序。代碼是非常有效的。不要被推遲,而是三個語句:編譯器在優化後只會產生一個循環!你甚至可以定義封閉的循環:

unsigned p[4][5]; 

for_range (Count, i, zero,three) 
    for_range(unsigned int, j, 4, 0) 
    { 
     p[i][j] = static_cast<unsigned>(i)+j; 
    } 

你顯然不能遍歷具有間隙的枚舉類型。

0

另一種方式:

for(unsigned i = n-1; i < n ; --i) 
{  
    // Iterates from n-1 to 0 
} 

Simillarly爲的size_t(無符號整數型)使用同樣的伎倆

for(std::size_t i = n-1; i < n ; --i) 
{  
    // Iterates from n-1 to 0 
}