Как поместить два оператора инкремента в цикл C++ 'for'?


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

что-то вроде:

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

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

8 69

8 ответов:

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

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 правило 199
Выражение инкремента в цикле будет выполнять никаких действий, кроме изменения одного параметр цикла к следующему значению для цикла.

Обоснование: Читабельность.

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

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

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

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

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

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

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

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

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

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