Счетчик для l oop ложно увеличивается после выполнения - PullRequest
1 голос
/ 20 апреля 2020

У меня есть 3 вложенных цикла, в которых код в любом случае не изменяет счетчики, мне нужно значение счетчика l oop самого верхнего уровня, чтобы использовать его позже в коде. Это выглядит так:

int i;
for( i = 0; !found && i <f_i.size();i++){
    for(unsigned int j = 0; !found && j < f_g.size();j++){
        for(unsigned int k = 0; !found && k < f_g.size();k++){
            ///Do Stuff
            found = (/*Condition that's fulfilled after 2 iterations on k*/);
        }
    }
}

//Stuff that uses i

Условие выполняется после 2 итерации самой внутренней l oop, поэтому i имеет значение 0 в этой точке. Используя GDB, я увидел, что значение i переходит на 1 после того, как условие проверено в самом верхнем l oop, что позже приводит к ошибкам в моей программе, или, что еще хуже, к выходу за пределы.

Спасибо заранее

Ответы [ 3 ]

2 голосов
/ 20 апреля 2020

Вот как работают циклы for. Приращение выполняется до того, как проверяется условие.

Правильный способ (проще для чтения, проще в обслуживании) сделать то, что вы хотите, - это добавить переменную вне l oop.

int index;

И установите его, когда найдете элемент:

        found = ...
        if (found) index = i;
2 голосов
/ 20 апреля 2020

Переменная i увеличивается из-за третьего выражения для l oop

int i;
for( i = 0; !found && i <f_i.size();i++){
                                    ^^^^  
    for(unsigned int j = 0; !found && j < f_g.size();j++){
        for(unsigned int k = 0; !found && k < f_g.size();k++){
            ///Do Stuff
            found = (/*Condition that's fulfilled after 2 iterations on k*/);
        }
    }
}

Чтобы избежать этого, вы можете написать, например,

int i;
for( i = 0; !found && i <f_i.size();){
    for(unsigned int j = 0; !found && j < f_g.size();j++){
        for(unsigned int k = 0; !found && k < f_g.size();k++){
            ///Do Stuff
            found = (/*Condition that's fulfilled after 2 iterations on k*/);
        }

    }
    i += !found;
}

Или вместо выражение expression

i += !found;

вы можете использовать оператор if наподобие

if ( !found ) ++i;

Также код будет выглядеть более читабельным, если переменная i будет инициализирована перед циклами, например, как

int i = 0;
while ( !found && i < f_i.size() ){
    for(unsigned int j = 0; !found && j < f_g.size();j++){
        for(unsigned int k = 0; !found && k < f_g.size();k++){
            ///Do Stuff
            found = (/*Condition that's fulfilled after 2 iterations on k*/);
        }

    }
    i += !found;
}
0 голосов
/ 20 апреля 2020

Как говорили другие (или, по крайней мере, подразумевается ): после ввода (самого крайнего) for l oop , переменная, i , будет увеличен в конце этого l oop, до условия, проверенного, чтобы увидеть, должен ли быть запущен другой l oop ...

... что если вы не «выпрыгнете» из l oop, используя оператор break!

Итак, следующий слегка измененный код будет не увеличение i (вообще), если found становится true во время первой итерации самой внешней l oop:

    int i;
    for (i = 0; !found && i < f_i.size(); i++) {
        for (unsigned int j = 0; !found && j < f_g.size(); j++) {
            for (unsigned int k = 0; !found && k < f_g.size(); k++) {
                ///Do Stuff
                found = (/*Condition that's fulfilled after 2 iterations on k*/);
            }
        }
        // If "found" becomes true, exit the loop immediately, AVOIDING THE INCREMENT:
        if (found) break;
    }

Итак, в то время как другие ответы очень хороши, и код Решения, которые они предлагают, совершенно верны, предложение здесь - это гораздо более «минимальная» корректировка вашего кода. Я надеюсь, что это помогает.

Примечание. Конечно, вы можете добавить аналогичные операторы break во внутренние циклы; однако, поскольку ваши переменные j и k объявлены локально для этих циклов, может показаться, что нежелательные приращения их значений не имеют значения. Кроме того, break нельзя использовать для выпрыгивания из нескольких вложенных циклов.

Также следует учитывать, что если переменная found равна true перед самым внешним for l oop встречается, что l oop не будет выполняться (очевидно) и, таким образом, переменная i не будет увеличиваться в этом случае.

...