Итерация по всем значениям от N до 0 включительно для значения без знака - PullRequest
1 голос
/ 09 декабря 2011

У меня есть этот код, который отлично работает для обычных целых чисел со знаком, и я пытаюсь написать эквивалентную версию, которая будет работать с size_t (поскольку в этом случае start и count являются целыми числами, и мне нужно, чтобы они были size_t):

int count,start;
for (start = (count-2)/2; start >=0; start--)
{
     someFunction( x, start, count); // x is to illustrate function has other parameters
}

Мне кажется, этот код достаточно прост для действительно простого решения, но я рисую пробел.

Ответы [ 4 ]

3 голосов
/ 09 декабря 2011

Вы можете переписать это так:

start = count/2;
while (start > 0){
    start--;
    someFunction( x, start, count);
}

В противном случае, единственная другая опция, о которой я могу подумать, - это выполнить какое-то нестандартное приведение в соответствие между подписанным и неподписанным ... или сделать что-то~(size_t)0 ...

Вот несколько нестандартных совместимых альтернатив:

for (start = (count-2)/2; (ssize_t)start >= 0; start--)
{
     someFunction( x, start, count);
}

for (start = (count-2)/2; start != ~(size_t)0; start--)
{
     someFunction( x, start, count);
}
1 голос
/ 09 декабря 2011
size_t cnt, start;
for (start = cnt/2; start-- > 0; ) { ... }
  • если cnt = 0: запуск начнется с нуля, код цикла никогда не будет выполнен; после цикла старт будет (size_t) -1
  • если cnt = 1: то же самое
  • если cnt> = 2: код цикла будет выполнен хотя бы один раз; на первой итерации старт будет (cnt / 2) -1; на последней итерации начало будет 0; после начала цикла будет (size_t) -1

РЕДАКТИРОВАТЬ, если OP действительно хочет выполнить цикл один раз для cnt = 1, необходима троичная:

for (start = (cnt==1) ? 1 : cnt/2; start-- > 0; ) { ... }
0 голосов
/ 09 декабря 2011

Вы можете исправить конечное условие из вашего исходного кода. -1/2 гарантированно равно 0 в C99, что заставляет тело цикла выполняться один раз, поэтому вам может потребоваться обработать count == 1 особенно, если это все еще требуется для поведения, когда типы не подписаны.

size_t count = something;
if (count > 1) {
    for (size_t start = (count-2)/2; start != SIZE_MAX; --start) {
        someFunction(x, start, count);
    }
}

Это работает, потому что мы знаем, что начальное значение start не может быть SIZE_MAX, потому что нет значения size_t, которое при делении на 2 дает SIZE_MAX.

Для более общих циклов, которые могут начинаться с SIZE_MAX и идти до 0 включительно, очевидно, что мы не можем выполнить проверку на выход перед телом цикла, потому что мы хотим, чтобы тело цикла выполнялось один раз для каждого значение size_t, поэтому нет значения, по которому мы можем выйти. Чтобы учесть этот случай:

size_t count = SIZE_MAX, start = SIZE_MAX;
do {
    someFunction(x, start, count);
} while (start-- != 0);

Во всех случаях SIZE_MAX можно заменить на -1, что является более общим в том смысле, что оно преобразуется в максимальное значение каждого типа без знака, но приводит к запутанным вопросам .

0 голосов
/ 09 декабря 2011

Как насчет использования значения по одному?

size_t start_plus_one;
for (start_plus_one = (count-2)/2+1; start_plus_one >=1; start_plus_one--)
{
     someFunction( x, start_plus_one-1, count); // x is to illustrate function has other parameters
}
...