Подтвердить что ты не робот

Как поместить два оператора инкремента в цикл С++ для цикла?

Я хотел бы увеличить две переменные в состоянии for -loop вместо одного.

Так что-то вроде:

for (int i = 0; i != 5; ++i and ++j) 
    do_something(i, j);

Каков синтаксис для этого?

4b9b3361

Ответ 1

Общей идиомой является использование оператора который оценивает оба операнда и возвращает второй операнд. Таким образом:

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 = я ++, a ++ эффективно анализируется как (x = я ++), a ++

Спасибо за все комментарии, это был интересный опыт обучения, и я много лет использую C!

Ответ 2

Попробуйте это

for(int i = 0; i != 5; ++i, ++j)
    do_something(i,j);

Ответ 3

Старайтесь не делать этого!

Из http://www.research.att.com/~bs/JSF-AV-rules.pdf:

Правило AV 199
Выражение приращения в цикле for не будет выполнять никаких действий, кроме как изменить один loop для следующего значения для цикла.

Обоснование: читаемость.

Ответ 4

for (int i = 0; i != 5; ++i, ++j) 
    do_something(i, j);

Ответ 5

Я пришел сюда, чтобы напомнить себе, как закодировать второй индекс в предложение increment цикла FOR, который, как я знал, может быть сделан главным образом из наблюдения за ним в образце, который я включил в другой проект, написанный на С++.

Сегодня я работаю на С#, но я был уверен, что он будет подчиняться тем же правилам в этом отношении, поскольку оператор FOR является одной из старейших структур управления во всем программировании. К счастью, недавно я провел несколько дней, точно документируя поведение цикла FOR в одной из моих старых программ на C, и я быстро понял, что в этих исследованиях были уроки, которые применимы к сегодняшней проблеме С#, в частности, к поведению второй индексной переменной.

Для неосторожного ниже приведено резюме моих наблюдений. Все, что я видел сегодня, тщательно наблюдая переменные в окне "Локали", подтвердило мое ожидание того, что оператор С# FOR ведет себя точно так же, как оператор C или С++ FOR.

  • В первый раз, когда цикл FOR выполняется, предложение increment (третий из его трех) пропускается. В Visual C и С++ приращение генерируется как три машинные команды в середине блока, который реализует цикл, так что начальный проход запускает только код инициализации один раз, затем перескакивает через блок инкремента для выполнения теста завершения. Это реализует функцию, в которой цикл FOR выполняет ноль или более раз, в зависимости от состояния его индекса и предельных переменных.
  • Если тело цикла выполняется, его последний оператор представляет собой переход к первой из трех команд инкремента, которые были пропущены первой итерацией. После их выполнения управление естественно попадает в тестовый код ограничения, который реализует среднее предложение. Результат этого теста определяет, выполняется ли тело цикла FOR, или управление переходит к следующей команде после перехода в нижней части области действия.
  • Так как управление передает из нижней части цикла цикла FOR в блок инкремента, индексная переменная увеличивается до того, как будет выполнен тест. Мало того, что это поведение объясняет, почему вы должны закодировать свои предельные предложения так, как вы узнали, но это влияет на любой дополнительный приращение, которое вы добавляете, через оператор запятой, потому что оно становится частью третьего предложения. Следовательно, он не изменяется на первой итерации, но находится на последней итерации, которая никогда не выполняет тело.

Если любая из ваших индексных переменных остается в области действия, когда цикл завершается, их значение будет на один выше порога, который останавливает цикл, в случае истинной индексной переменной. Аналогично, если, например, вторая переменная инициализируется до нуля до ввода цикла, ее значение в конце будет счетчиком итераций, предполагая, что это инкремент (++), а не декремент, и что ничего в тело цикла меняет свое значение.

Ответ 6

Я согласен с податливостью. Увеличение двух переменных связано с ошибкой, особенно если вы проверяете только один из них.

Это читаемый способ сделать это:

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.

Ответ 7

int main(){
    int i=0;
    int a=0;
    for(i;i<5;i++,a++){
        printf("%d %d\n",a,i);
    } 
}

Ответ 8

Используйте математику. Если две операции математически зависят от итерации цикла, почему бы не выполнить математику?

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);

Особенно, если вы переходите к функции по значению, то вы должны получить то, что делает именно то, что вы хотите.