Как поместить два оператора приращения в цикл C ++ для for?
-
22-07-2019 - |
Вопрос
Я хотел бы увеличить две переменные в условии for
-loop вместо одной.
Так что-то вроде:
for (int i = 0; i != 5; ++i and ++j)
do_something(i, j);
Какой синтаксис для этого?
Решение
Распространенная идиома - использование оператора запятой , который оценивает оба операнда и возвращает второй операнд. Таким образом:
for(int i = 0; i != 5; ++i,++j)
do_something(i,j);
Но действительно ли это оператор запятой?
Теперь, написав это, комментатор предположил, что это действительно какой-то особый синтаксический сахар в операторе for, а не оператор запятой вообще. Я проверил это в GCC следующим образом:
int i=0;
int a=5;
int x=0;
for(i; i<5; x=i++,a++){
printf("i=%d a=%d x=%d\n",i,a,x);
}
Я ожидал, что x выберет исходное значение a, поэтому он должен был отображать 5,6,7 .. для x. Я получил это
i=0 a=5 x=0
i=1 a=6 x=0
i=2 a=7 x=1
i=3 a=8 x=2
i=4 a=9 x=3
Однако, если я заключил в скобки выражение, чтобы заставить парсер действительно увидеть оператор запятой, я получу это
int main(){
int i=0;
int a=5;
int x=0;
for(i=0; i<5; x=(i++,a++)){
printf("i=%d a=%d x=%d\n",i,a,x);
}
}
i=0 a=5 x=0
i=1 a=6 x=5
i=2 a=7 x=6
i=3 a=8 x=7
i=4 a=9 x=8
Сначала я думал, что это показывает, что он вообще не работает как оператор запятой, но, как оказалось, это просто проблема приоритета - у оператора запятой есть минимально возможный приоритет , поэтому выражение x = i ++, a ++ эффективно анализируется как (x = i ++), a ++
Спасибо за все комментарии, это был интересный опыт обучения, и я использую C уже много лет!
Другие советы
Попробуйте это
for(int i = 0; i != 5; ++i, ++j)
do_something(i,j);
Постарайся не делать этого!
От http://www.research.att.com/~bs/JSF-AV-rules.pdf :
AV Rule 199
Выражение приращения в цикле for не будет выполнять никаких действий, кроме изменения одного параметр цикла до следующего значения для цикла. Р>Обоснование: удобочитаемость. Р>
for (int i = 0; i != 5; ++i, ++j)
do_something(i, j);
Я пришел сюда, чтобы напомнить себе, как кодировать второй индекс в предложении приращения цикла FOR, что, как я знал, можно сделать главным образом из наблюдения за ним в образце, который я включил в другой проект, написанный на C ++. р>
Сегодня я работаю в C #, но я был уверен, что он будет подчиняться тем же правилам в этом отношении, поскольку оператор FOR является одной из самых старых управляющих структур во всем программировании. К счастью, недавно я потратил несколько дней на точное документирование поведения цикла FOR в одной из моих старых программ на C, и я быстро понял, что в этих исследованиях были извлечены уроки, относящиеся к сегодняшней проблеме C #, в частности к поведению второй индексной переменной. . р>
Для неосторожных ниже приводится краткое изложение моих наблюдений. Все, что я видел сегодня, внимательно наблюдая за переменными в окне Locals, подтвердило мои ожидания, что оператор C # FOR ведет себя точно так же, как оператор C или C ++ FOR.
<Ол>Если одна из ваших индексных переменных останется в области видимости после окончания цикла, их значение будет на единицу выше порогового значения, которое останавливает цикл, в случае истинной индексной переменной. Аналогично, если, например, вторая переменная инициализируется в ноль до ввода цикла, ее значением в конце будет счетчик итераций, при условии, что это приращение (++), а не уменьшение, и что ничего в тело цикла меняет свое значение.
Я согласен с squelart. Увеличение двух переменных подвержено ошибкам, особенно если вы тестируете только одну из них.
Это читабельный способ сделать это:
for(int i = 0; i < 5; ++i) {
++j;
do_something(i, j);
}
Циклы For
предназначены для случаев, когда ваш цикл выполняется на одной возрастающей / убывающей переменной. Для любой другой переменной измените ее в цикле.
Если вам нужно привязать j
к i
, почему бы не оставить исходную переменную как есть и добавить i
?
for(int i = 0; i < 5; ++i) {
do_something(i,a+i);
}
Если ваша логика более сложная (например, вам нужно фактически отслеживать более одной переменной), я бы использовал цикл while
.
int main(){
int i=0;
int a=0;
for(i;i<5;i++,a++){
printf("%d %d\n",a,i);
}
}
Используйте математику. Если две операции математически зависят от итерации цикла, почему бы не выполнить математические вычисления?
int i, j;//That have some meaningful values in them?
for( int counter = 0; counter < count_max; ++counter )
do_something (counter+i, counter+j);
Или, более конкретно, ссылаясь на пример OP:
for(int i = 0; i != 5; ++i)
do_something(i, j+i);
Особенно, если вы переходите в функцию по значению, тогда вы должны получить что-то, что делает именно то, что вы хотите.