Ответ 1
Как насчет:
for (unsigned i = n ; i-- > 0 ; )
{
// do stuff with i
}
Моя первая попытка reverse для цикла, которая делает что-то n раз, была чем-то вроде:
for ( unsigned int i = n-1; i >= 0; i-- ) {
...
}
Этот терпит неудачу, потому что в беззнаковой арифметике i
гарантировано всегда больше или равно нулю, поэтому условие цикла всегда будет истинным. К счастью, gcc-компилятор предупредил меня о "бессмысленном сравнении", прежде чем мне пришлось задаться вопросом, почему цикл выполнялся бесконечно.
Я ищу элегантный способ решения этой проблемы, имея в виду, что:
Любые идеи? Спасибо:)
Как насчет:
for (unsigned i = n ; i-- > 0 ; )
{
// do stuff with i
}
for ( unsigned int loopIndex = n; loopIndex > 0; --loopIndex ) {
unsigned int i = loopIndex - 1;
...
}
или
for ( unsigned int loopIndex = 0; loopIndex < n; ++loopIndex ) {
unsigned int i = n - loopIndex - 1;
...
}
for ( unsigned int i = n; i != 0; i-- ) {
// do something with i - 1
...
}
Обратите внимание, что если вы используете С++, а также C, использование!= является хорошей привычкой, когда вы переключаетесь на использование итераторов, где <= и т.д. могут быть недоступны.
for ( unsigned int i = n; i > 0; i-- ) {
...
i-1 //wherever you've been using i
}
Я бы использовал
for ( unsigned int i = n; i > 0; ) {
--i;
...
}
он почти такой же, как ответ skizz ', (он пропускает окончательный ненужный декремент, но компилятор должен его оптимизировать), и на самом деле пройдет обзор кода. Каждый стандарт кодирования, с которым мне приходилось работать, не имел мутации в условном правиле.
Почему бы просто:
unsigned int i = n;
while(i--)
{
// use i
}
Это отвечает всем требованиям, перечисленным в теле вопроса.
Он не использует ничего, что может привести к сбою проверки кода или нарушению стандарта кодирования.
Единственное возражение, которое я мог видеть, это то, что OP действительно настаивал на цикле for
, а не на простом способе генерации я = (n-1).. 0.
Может, так? ИМХО его понятно и понятно. Вы можете опустить if (n >= 1), если он неявно известен как-то.
if(n>=1) {
// Start the loop at last index
unsigned int i = n-1;
do {
// a plus: you can use i, not i-1 here
} while( i-- != 0 );
}
Другая версия:
if(n>=1) {
unsigned int i = n;
do {
i--;
} while( i != 0 );
}
Первый код без оператора if будет выглядеть следующим образом:
unsigned int i = n-1;
do {
} while( i-- != 0 );
Или вы можете положиться на поведение оболочки unsigned int
, если вам нужно индексировать от n-1 до 0
for(unsigned int i = n-1; i < n; i--) {
...
}
for ( unsigned int i = n; i > 0; i-- ) {
unsigned int x = i - 1;
// do whatever you want with x
}
Конечно, не элегантный, но он работает.
for (unsigned int i = n-1; i<(unsigned int)-1; i--)
ОК, его "нечеткая кольцевая арифметика".
Единственная причина, по которой я упоминаю этот вариант, состоит в том, что я не видел его в списке.
for ( unsigned int i = n-1; i < n; i-- ) {
...
}
Полностью против интуиции, но он работает. причина, по которой она работает, состоит в том, что вычитание 1 из 0 дает наибольшее число, которое может быть представлено целым числом без знака.
В общем, я не думаю, что это хорошая идея для работы с целыми целыми числами без подзарядки, а также при вычитании.
Просто, просто остановитесь на -1:
for( unsigned int i = n; i != -1; --i )
{
/* do stuff with i */
}
edit: не знаю, почему это происходит. он работает, и это проще и очевиднее любого из вышеперечисленных.
for ( unsigned int i = n; i > 0; i-- ) {
...
}
Должно работать нормально. Если вам нужно использовать переменную i
в качестве индекса в массиве, сделайте следующее:
array[i-1];
Hm. Вот ваши варианты:
i=0
как условие прерывания. Петля не будет выполняться, когда я достигнет 0, поэтому выполните 1-ю итерацию содержимого цикла для i=0
после выхода цикла.for ( unsigned int i = n-1; i > 0; i-- ) {
doStuff(i);
}
doStuff(0);
i=0
и break
. Не рекомендуется, потому что теперь вы проверяете значение я дважды в цикле. Также использование перерыва в цикле обычно рассматривается как плохая практика.for ( unsigned int i = n-1; i >= 0; i-- ) {
doStuff(i);
if (i=0) break;
}
unsigned index;
for (unsigned i=0; i<n; i++)
{
index = n-1 - i; // {i == 0..n-1} => {index == n-1..0}
}
Так как это не стандарт для цикла, я, скорее всего, использовал бы цикл while, например:
unsigned int i = n - 1;
while (1)
{
/* do stuff with i */
if (i == 0)
{
break;
}
i--;
}
Это не проверено, но вы можете сделать следующее:
for (unsigned int i, j = 0; j < n; i = (n - ++j)) {
/* do stuff with i */
}
Используйте две переменные: одну для подсчета, а другую для индекса массива:
unsigned int Index = MAX - 1;
unsigned int Counter;
for(Counter = 0; Counter < MAX; Counter++)
{
// Use Index
Index--;
}
for ( unsigned int i = n-1; (n-i) >= 0; i-- ) {
// n-i will be negative when the loop should stop.
...
}
e.z:
#define unsigned signed
for ( unsigned int i = n-1; i >= 0; i-- ) { ...
}