Урок №76. Массивы и циклы

  Юрий  | 

  |

  Обновл. 13 Сен 2021  | 

 87291

 ǀ   23 

На этом уроке мы рассмотрим использование массивов с циклами, а также подводные камни, с которыми вы можете при этом столкнуться.

Зачем использовать циклы с массивами?

Рассмотрим случай, когда нужно вычислить средний балл всех студентов в группе. Используя отдельные переменные:

Мы получим много объявлений переменных и, следовательно, много кода — а это всего лишь 5 студентов! А представьте, если бы их было 30 или 150.

Кроме того, чтобы добавить нового студента, нам придется объявить новую переменную, инициализировать её и добавить в переменную totalScore. И это всё вручную. А каждый раз при изменении старого кода есть риск наделать новых ошибок. А вот с использованием массива:

Количество объявленных переменных сократится, но в totalScore по-прежнему придется заносить каждый элемент массива вручную. И, как указано выше, изменение количества студентов означает, что формулу totalScore необходимо будет изменять также вручную.

Если бы был только способ автоматизировать этот процесс.

Циклы и массивы


Из предыдущего урока мы уже знаем, что индекс массива не обязательно должен быть константным значением — он может быть и обычной переменной. Это означает, что мы можем использовать счетчик цикла в качестве индекса массива для доступа к элементам и выполнения с ними необходимых математических и других операций. Это настолько распространенная практика, что почти всегда при обнаружении массива, вы найдете рядом с ним цикл! Когда цикл используется для доступа к каждому элементу массива поочередно, то это называются итерацией по массиву. Например:

Это решение идеально подходит как в плане удобства и чтения, так и поддержки. Поскольку доступ к каждому элементу массива выполняется через цикл, то формула подсчета суммы всех значений автоматически настраивается с учетом количества элементов в массиве. И для вычисления средней оценки нам уже не нужно будет вручную добавлять новых студентов и индексы новых элементов массива!

А вот пример использования цикла для поиска в массиве наибольшего значения (наилучшей оценки среди всех студентов в группе):

Здесь уже используется переменная maxScore (не из цикла) для отслеживания самого большого значения массива. Сначала инициализируем maxScore значением 0, что означает, что мы еще не видели никаких оценок. Затем перебираем каждый элемент массива и, если находим оценку, которая выше предыдущей, присваиваем её значение переменной maxScore. Таким образом, maxScore всегда будет хранить наибольшее значение из всех элементов массива.

Использование циклов с массивами

Циклы с массивами обычно используются для выполнения одной из трех следующих задач:

   Вычислить значение (например, среднее или сумму всех значений).

   Найти значение (например, самое большое или самое маленькое).

   Отсортировать элементы массива (например, по возрастанию или по убыванию).

При вычислении значения, переменная обычно используется для хранения промежуточного результата, который необходим для вычисления конечного значения. В примере, приведенном выше, где мы вычисляем средний балл, переменная totalScore содержит сумму значений всех рассмотренных элементов.

При поиске значения, переменная обычно используется для хранения наилучшего варианта (или индекса наилучшего варианта) из всех просмотренных. В примере, приведенном выше, где мы используем цикл для поиска наивысшей оценки, переменная maxScore используется для хранения наибольшего количества баллов из просмотренных ранее элементов массива.

Сортировка массива происходит несколько сложнее, так как в этом деле используются вложенные циклы (но об этом уже на следующем уроке).

Массивы и «ошибка неучтенной единицы»


Одной из самых сложных задач при использовании циклов с массивами является убедиться, что цикл выполняется правильное количество раз. Ошибку на единицу (или «ошибку неучтенной единицы») сделать легко, а попытка получить доступ к элементу, индекс которого больше, чем длина массива, может иметь самые разные последствия. Рассмотрим следующую программу:

Здесь проблема состоит в неверном условии оператора if в цикле for! Объявленный массив содержит 5 элементов, проиндексированных от 0 до 4. Однако цикл внутри перебирает элементы от 0 до 5. Следовательно, на последней итерации в цикле for выполнится:

Но ведь students[5] не определен! Его значением, скорее всего, будет простой мусор. И в итоге результатом выполнения цикла может быть ошибочный maxScore.

Однако представьте, что бы произошло, если бы мы ненароком присвоили значение элементу students[5]! Мы бы могли перезаписать другую переменную (или её часть) или испортить что-либо — эти типы ошибок очень трудно отследить!

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

Тест

Задание №1

Выведите на экран следующий массив с помощью цикла:

Подсказка: Используйте трюк с sizeof (из предыдущего урока) для определения длины массива.

Ответ №1

Задание №2

Используя массив из задания №1:

Попросите пользователя ввести число от 1 до 9. Если пользователь введет что-либо другое — попросите его снова ввести число и так до тех пор, пока он не введет корректное значение из заданного диапазона. Как только пользователь введет число от 1 до 9, выведите массив на экран. Затем найдите в массиве элемент с числом, которое ввел пользователь, и выведите его индекс.

Для обработки некорректного ввода используйте следующий код:

Ответ №2

Задание №3

Измените следующую программу так, чтобы вместо maxScore с наибольшим значением, переменная maxIndex содержала индекс элемента с наибольшим значением:

Ответ №3


Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (334 оценок, среднее: 4,91 из 5)
Загрузка...

Комментариев: 23

  1. Сашуня:

    Первое:

    Второе:

    Третье:

  2. Александр:

    задание 2 со второго раза получилось

  3. Евгений:

    Первое задание:

  4. Jaroshevskii:

    Спасибо большое за лучший русскоязычный сай по изучению C++

    Задание №1

    Задание №2

    Задание №3

  5. кисин:

    Первое задание

  6. Юрий:

    Задание №3

  7. Yana:

    Знаю, что без цикла , но имеет право жить это решение второго задания? Меня пугает предупреждение C6385. Позже постараюсь решить с циклом, когда пойму(

    1. Андрей:

      в проверке диапазона при использовании || у тебя всегда будет true нужно использовать && для наглядности почитайте про круги эйлера

  8. Onium:

    Задание 3

  9. Onium:

    Второе задание

  10. Павел:

    Вопрос по задаче 2. Почему если пишу "\n Не угадал! \n" при выполнении отступ будет 1 пример:

    Введите число от 1 до 9: 45

    Не угадал!
    Введите число от 1 до 9:

    А если пишу "\n Не угадал! \n\n" то всё получается как задумал(cout<<"\n Не угадал! "<<endl; не канает, т.к. получается результат ример 1):

    Введите число от 1 до 9: 45

    Не угадал!

    Введите число от 1 до 9:

    Сама прога:

    1. Антон:

      Когда ты вводишь значение через std::cin автоматически добавляется абзац, соответственно на самом деле это выглядит как \n\nНе угадал\n\n

  11. Вячеслав:

    третье задание:

    1. ОЛЕГ-777:

      Уважаемый Вячеслав!!!
      Эта программа выводит наибольшее значение а не индекс наибольшего элемента. А в задании требуется вывести индекс наибольшего элемента.

  12. Вячеслав:

    вот первое задание:

  13. Алена:

    Такая проверка ввода излишне?

    1. Павел:

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

  14. Роман:

    Мне кажется не обязательно делать проверку if (std::cin.fail()).
    И можно совместить вывод массива и поиск индекса.

  15. Torgu:

    Все время сталкиваюсь с одной и той же проблемой, но только сейчас решил спросить. Зачастую не получается использовать уникальную инициализацию в циклах/условиях. Конкретно есть следующий отрывок кода из второго задания:

    Строчка "index{ count }" выдает ошибку "требуется точка с запятой", и только стоит мне изменить на прямую инициализацию "index = count", так все идеально работает. На уникальную инициализацию существуют какие-то ограничения?

    1. Torgu:

      UPD: если кому-то интересно, понял в чем проблема на опыте: { } — инициализация, а не присвоение значения, то есть данные скобки можно использовать только один раз для конкретно переменных — при ее инициализации. А я пытался использовать второй раз

  16. Алибек:

    2 задача:

  17. Валерий:

    Много же тебе еще переводить! Хватит ли духу до конца? Вообще нужное дело!

    1. Фото аватара Юрий:

      Уже можно сказать рефлекс выработался 🙂 Сам не знаю, пока будет свободное время — буду переводить.

Добавить комментарий для Torgu Отменить ответ

Ваш E-mail не будет опубликован. Обязательные поля помечены *