Вопрос

[EDIT]Упс, в коде была ошибка, и теперь все ответы на вопрос кажутся странными, но в основном цикл for раньше был for(i=0;я<15;я++).Я также отредактировал, чтобы сделать вопрос более ясным.[/EDIT]

Я пытаюсь создать цикл for, который проверяет массив из 16 элементов, поэтому он зацикливается от 0 до 15.Позже я использую переменную i, однако иногда i == 16, что вызывает проблемы из-за выхода за пределы.

У меня есть решение, но оно не кажется элегантным, и мне кажется, что я что-то упускаю.Я пробовал циклы while, но мне никогда не удавалось заставить цикл изменяться от 0 до 15 и никогда не заканчиваться на значении больше 15.

Есть ли способ заставить цикл пройти и проверить все 16 элементов массива, не превышая при этом 15 в конце цикла?

int i;

for(i=0; i<16; i++)
{
    someClass.someMethod(i);

    if(someClass.Test())
    {
        break;
    }
}



if (i == 16)
{
    i = 15;
}
Это было полезно?

Решение

Я предлагаю использовать другую переменную, кроме i после завершения вашего цикла.Критерием использования цикла for вместо цикла while является то, что вы заранее точно знаете, сколько раз цикл for будет выполняться.Если вы это уже знаете, просто установите конечную стоимость вашего цикла в какую-нибудь другую переменную и используйте ее вместо указания i двойная цель.

int j = 15;

for(int i=0; i <= j; i++)
{
    someClass.array[i];
}

// continue on using j, which value hasn't changed

Другие советы

Ну, для начала, ваш пример кода зацикливается от 0 до 14.Но если вы выполняете цикл от 0 до 15, естественно, мне должно быть 16. до цикл может закончиться.Что происходит, так это то, что оно становится 16, ТОГДА ваш цикл замечает, что он выходит за пределы, и вырывается.Если вы хотите, чтобы он закончился на 15, честно говоря, проще всего просто уменьшить значение сразу после окончания цикла.

При последней проверке i увеличивается до 16, что не меньше 15, поэтому цикл завершается со значением i, равным 16.

Возможно, полезно знать следующее:

for (before; check; after) { body } 

это то же самое, что:

before 
while(check) { 
  body 
  after 
} 

Если вы подумаете над циклом for в этом термине, возможно, вы легко поймете, почему на выходе i равно 16.

Кажется, в вашем подходе есть некоторые фундаментальные недостатки.

  1. На самом деле вам не следует использовать индексную переменную за пределами цикла.
  2. Вам следует использовать переменную или функцию, чтобы определить предел цикла.
  3. Вместо числовых индексов было бы лучше использовать итераторы.
  4. Универсальные алгоритмы могут устранить необходимость в циклах.

Всего лишь мои 0,02 доллара.

Итак, если вы проверяете массив из 16 элементов, обычно вы делаете это:

for(i=0; i<16; i++)

Что касается работ, то они начинаются с первого утверждения из трех:

i=0

Затем он выполняет проверку во втором операторе:

i < 16 // True here, since 0 < 16

Это происходит перед вашим циклом.Затем он запускает блок вашего цикла с этим набором:

someClass.array[i]; //0

Наконец, он делает последнее утверждение:

i++

Затем он последовательно повторяет второе и третье утверждения.

Перед последним запуском i == 14, затем выполняется i++, устанавливая i равным 15, и выполняется блок.Наконец, он делает i++, устанавливая:

i==16

На этом этапе условие больше не выполняется:

i < 16 // False, since i==16

На этом этапе ваш блок не выполняется, но для i все еще установлено значение 16.

Вы, должно быть, что-то пропустили.

В этом цикле он даже не достигнет 15, вам нужно будет сказать i <= 15, как только i = 14 он запустится один раз и выйдет из строя.

А for цикл эквивалентен следующему while петля:

i = 0;
while(i < 16) {
    someClass.array[i];

    i++;
} // while

i необходимо достичь 16, чтобы правильно выйти из цикла.

Технически существуют способы написать цикл так, что i равно 15 при выходе из цикла, но делать этого не следует:

int i = 0;
while (1) {
    someclass.someMethod(i);
    if (i < 15) {
        i++;
    } else {
        break;
    }
}

Да, он делает то, что вы просите.Но поток ужасный.

Вы не можете добиться этого с помощью встроенных структур цикла, и, как сказал Билл Ящерица, вы, вероятно, не захотите повторно использовать переменную цикла for.

Но если вы действительно этого хотите, вот способ сделать это.Хитрость заключается в том, чтобы поместить условие цикла в середину цикла:

int i = 0;
while (true)
{
    someclass.array[i];
    if (i == 15)
        break;
    ++i;
}

Здесь важно понять, что существует 17 различных ответов на вопрос «Какое значение i обеспечивает успех теста?».Либо i может находиться в {0, 1, ..., 15}, либо отсутствие значения i приводит к успешному завершению теста, что в данном случае обозначается i == 16.Поэтому, если я ограничен только 16 значениями, на вопрос невозможно ответить.

Существуют законные случаи, когда вы не хотите выходить за пределы последнего допустимого значения.Например, если у вас было 256 значений и по какой-то причине вам нужно считать только один байт.Или, как это недавно случилось со мной, вы хотите проверить только каждый i-й элемент массива, и последнее добавление к вашему итератору выводит вас далеко за пределы конца массива.В этих случаях разворачивание цикла необходимо.

Однако для этой проблемы было бы проще использовать флаг:

bool flag = false;
for (int i = 0; i < 15; ++i) 
{
    someClass.someMethod(i);

    if (someClass.Test())
    {
        flag = true;
        break;
    }
}

Тогда станет ясно, был ли тест успешным.

Если ваш цикл завершается естественным образом, а не прерыванием, i воля быть 16.Нет никакого способа избежать этого.Ваш код вполне приемлем, если вы хотите, чтобы i в конечном итоге было равно 15 или меньше:

int i;
for (i=0; i<16; i++) {
    someClass.someMethod(i);
    if (someClass.Test())
        break;
}
if (i == 16)
    i = 15;

Все, что меняется i с 16 по 15 после того, как тело цикла выполнит:

if (i == 16) i = 15;
i = (i == 16) ? 15 : i;
i = MAX (15,i); /* where MAX is defined :-) */

и так далее.

Однако это предполагает, что i будет использоваться для чего-то значимого в качестве постусловия по отношению к этому циклу.Я считаю, что это случается редко, люди склонны повторно инициализировать его перед повторным использованием (например, в другом цикле for).

Кроме того, из-за того, что вы делаете, очень сложно (даже невозможно) определить в качестве постусловия, завершился ли ваш цикл нормально или он завершился преждевременно, потому что someClass.Test() вернулось верно для i == 15.Это означает, что использование i для принятия дальнейшего решения чревато опасностью.

Мой вопрос был бы: Почему ты думаешь, тебе нужно уйти? i 15 или меньше?

Я пытаюсь сделать петлю, который проверяет массив 16 элементов, поэтому он переходит от 0 до 15.Затем я использую переменную I позже, однако иногда I == 16, что вызывает проблемы, находясь за пределами границ.

Вам нужно проверить случай, когда ваш цикл for не прервался, потому что эта информация определяет, действительно ли то, что вы хотели сделать с i, действительно.

Есть несколько способов сделать это.Один из них — отслеживать его в виде логического значения, например «foundClass» или «testSucceeded».По умолчанию установите значение false, а затем установите значение true во время перерыва.Заключите любое использование i позже в функции в блоках «if (foundClass) { }».

Другой вариант — просто делать то, что вы сделали.Хотя ваш запасной вариант выглядит совсем не так.Если вы устанавливаете i равным 15, вы лжете своему коду и сообщаете ему, что someClass.Test() завершился успешно для i == 15, что не соответствует действительности.Не устанавливайте неправильное значение только для того, чтобы в дальнейшем в вашем коде не возникало ошибок.Гораздо лучше проверить границы фактического использования i позже в коде.

for(int i=0; i<17; i++)
{    
  if(i<16)
  {
     someClass.someMethod(i); 
     if(someClass.Test())   
     {        
       break;    
     }
  }
  else if(i==16)
  {
     i=15;
  }
}

если вы говорите, что у вас есть массив из 16 элементов, вам не нужно его определять, используйте массив, чтобы получить эту информацию (НЕ ДУБЛИРУЙТЕ ИНФОРМАЦИЮ)

впоследствии, если вы хотите снова получить последний индекс, используйте массив для получения этой информации.

for(int i = 0; i < myArray.length; ++i){
       myArray[i].somemethod();
}
// lastindex = myArray.length-1;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top