Одномерный массив в C++ для начинающих

  • Массив представляет нечто целое, что содержит целый набор однотипных элементов.
Мобильный телефон представляет из себя своеобразный массив, который содержит в себе набор контактов.
Спичечная коробка представляет из себя своеобразный массив, который содержит в себе набор спичек.
Квартирный дом представляет из себя своеобразный массив, который содержит в себе набор хозяев квартир.
Парк машин представляет из себя своеобразный массив, который содержит в себе коллекцию машин.
В общем, массив напоминает обычную коробку с хранимыми внутри вещами материального мира, например, продуктами.
Сам массив удобен для хранения, но ценны хранимые внутри него элементы, а не непосредственно массив. Конечно в мире материальном коробка может оказаться золотой, потому и дороже своих внутренностей, но в мире программирования массивы являются обычными контейнерами хранения.
Обрабатывая массивы, программист работает не с массивом, как с таковым, а с его внутренними данными. В отличие от материального мира, где хранимые объекты могут не обладать свойством самоидентификации, массивы мира программистов всегда сами нумеруют элементы своих колллекций (обычные массивы) или дают элементу коллекции признаки идентификации (ассоциативные массивы).
  • В массиве главную роль играют его элементы, а сам массив играет второстепенные роли.
  • Каждый элемент коллекции массива всегда имеет какой-то признак своей идентификации. Признаком идентификации элемента обычного массива всегда является число, которое есть номер ячейки массива. Называется число, номер ячейки, индексом массива. По этому номеру всегда можно идентифицировать и обработать некоторый элемент из массива.
Надеюсь, смысл понятен. Массив — это хранилище, контейнер. Обрабатываются его элементы, а не сам массив. Каждый элемент массива идентифицируется или номером, или каким-то задаваемым программистом ключом. В обычных массивах, а сейчас вы изучаете обычные массивы, идентификация происходит по номеру. Компилятор сам нумерует элементы массива, нумерация в С++ начинается с нуля.
Язык С++ является надмножеством языка С. В первых версиях языка С++ программистам приходилось работать с массивами так же, как программистам С. Самые обычные массивы относятся к фундаментальным типам данных и являются составными типами. Есть два способа работы с такими, обычными, массивами. Первый способ — выделение памяти под заранее известное число элементов, второй способ — выделение памяти в ходе работы программы под задаваемое количество элементов. Второй способ требует ручного управления памятью, что новичкам в большинстве случаев неудобно.
Бывает так, что известно количество элементов, которое будет хранится в массиве, известно, что это количество элементов не изменится за всю жизнь работы программы. В таких случаях используют обычные массивы. Для примера подобной необходимости несколько жизненных вариантов:
Воллейбольная площадка: больше шести игроков на ней не играет.
Квартира жилого дома: во всём доме может не быть квартир, с количеством комнат, превышающим 5.
Виды осадков: выпадающие на планете Земля виды осадков ограничены некоторым числом (дождь, снег, град)
Штат сотрудников: штат сотрудников может быть строго фиксирован
Именно для таких случаев и используется самый обычный массив. Количество элементов таким массивам задаётся непосредственно в исходном коде программы. Изменить количество элементов в ходе работы программы таким массивам невозможно. Такие массивы назывются статически-создаваемыми массивами, иногда называют статическими, но слово статические плохо подходит из-за существования ключевого слова static.

Статический массив на самом деле немного другой:

Имеется различие в работе первого и второго. Описание различий выходит за рамки статьи. Но имейте в виду, что есть такой дефект в терминологии. Вроде и принято называть обычный массив статическим, но оно неправильно как-то выходит в конечном итоге.
  • Не путайте статические массивы со статически-создаваемыми. Говорите правильно.
От нас требуется массиву сообщить, какие типы он должен хранить в себе и количество элементов. Зная эти составляющие, компилятор выделит необходимую память для всего массива.

В квадратных скобках указывается число хранимых элементов.
В подавляющем большинстве случаев интересен не сам массив, а то, что он содержит. Почти всегда обработка массивов предполагает обработку его элементов, причём часто предпалагается обработка всех элементов из массива. Для обхода элементов массивов используют циклы. Одна и та же обработка на каждый отдельный элемент массива сама собой напрашивает использование циклов: повторение одних и тех же действий.
В языке С++ численный отсчёт начинается с нуля. В некоторых других языках программирования с единицы. Немного нестандартное для обычного человека начало отсчёта сбивает с толку многих начинающих программистов: трудно первое время ориентироваться, постоянно нарушаются некоторые границы.

Эта ошибка не контроллируется компилятором. Программист, пишуший код, а не компилятор должен контроллировать возникновение такой ситуации и не допускать её. Из-за того, что отсчёт в С++ начинается с нуля, последним индексом массива, хранящего 10 элементов, будет индекс 9:

  • Для любого массива C++, хранящего N элементов, индекс последнего элемента всегда N-1, а индекс первого элемента 0
Можно подстроить отсчёт под себя, выделив массиву на 1 элемент больше, но делать такое не нужно. Пишущий на C++ должен писать, придерживаясь правил C++. Следование принципу использвания правил языка, на котором пишешь, поможет вам в будущем.
Каждый элемент массива представляет из себя переменную с указанным массиву типом. В отличие от обычной переменной, которой название даёт программист, элементы обычного массива подобны автонумерующимся переменным. Т. е. название массива вместе с индексом элемента = переменная. Работать с элементами массива можно абсолютно так же, как работаем с переменными. Единственное отличие — индексация.

Подведём промежуточные итоги:
  • Для создания обычного массива компилятору нужно указать тип хранимых элементов и предполагаемое количество ячеек для хранения тех элементов.
  • Массивам обязательно нужно указывать тип, как и обычным переменным. Типы массивов задаются те же, что для переменных.
  • Количество хранимых элементов указывается в квадратных скобках во время объявления массива.
  • Квадратные скобки могут служит некоторого рода индикатором, сообщающем о том, что работа происходит с массивом.
  • Каждый отдельный элемент обычного массива вытаскивается по индексу, т. е. по номеру ячейки.
  • Номер вытаскиваемого элемента надо начинать расчитывать с ноля, а не единицы.
  • Номера элементов массива называют индексами массива.
  • Массив возможно инициализировать значениями. Без инициализации массива значениями внутр массива оказывается информационный мусор.
На этом промежуточные итоги подведены. Сейчас я напишу то, что где-то вычитал, но сам не понял, что хотел сказать авторы:
  • Внешние и статические массивы можно инициализировать
  • Автоматические и регистровые массивы инициализировать нельзя
Идём дальше.
Инициализируются массивы с помощью фигурных скобок.

Если нужно инициализировать массив нулями, то это можно делать следующим образом:


В общем, не нужно каждый ноль прописывать вручную для инициализации нулями. Но не запутайтесь, нельзя инициализировать массив, например, одними единицами показанным в #8.1 способом. #8.1 подходит только для нолей.
Правилами языка С++ разрешено использовать пустые скобки при инициализации массивов. В случае использования пустых квадратных скобок компилятор сам определит, сколько памяти массиву нужно выделить.

Узнать, сколько байт уходит на один элемент массива, можно так:
Узнать, сколько элементов может поместиться в массив, можно так:
Переходим к написанию простеньких примеров.

  • Количество элементов обычного массива задаётся только константным значением.
Количество элементов обычному массиву можно задать только неизменяемым значением. Задать такое значение возможно только в исходном коде программы. Хотя некоторые компиляторы могут компилировать коды, в которых количество указывается переменной, допускающей изменения, такие действия не приветствуются.

Если массив требует себе расширения или наоборот, сужения, то обычный статически-создаваемый массив не подходит. Изменять число элементов в нём невозможно. Хранит он только фиксированное число элементов. Хоть размер такому, как в листинге #11, и можно задать во время работы программы, задать его можно единожды и изменениям он не подлежит.
Массив из листинга #11 может обманывать. Возможно подумать, что он умеет изменять пространство для хранимых в себе элементов, но на самом дее это совсем не так. Изменять пространство под хранимые элементы можно только с помощью указателей на массивы, а умеют это делать самостоятельно массивы из библиотек: STL, BOOST и т. п.
В С++ нельзя применять операции к самому массиву как к его элементам. Он как коробка, а компилятор такой: "Зачем мне коробка?". Коробка отличается от хранимых внутри неё элементов.
Иногда массивы называют матрицами. Пока что вы поверхностно ознакомлены с самым простым типом массива. Можете встретить задачу сложения одномерных матриц/массивов. Чтобы решить такого вида задачу, нужно иметь представление о том, как складывать между собой две цепочки чисел. На самом деле ничего сложного нет: каждый элемент такой цепочки складывается с элементом другой цепочки, а связь складываемых элементов определяется номером элемента в цепочке.
1 2 3 4 5
+
7 5 3 2 0
=========
8 7 6 6 5
Таким образом, можно говорить о том, что {1 2 3 4 5} + {7 5 3 2 0} = {8 7 6 6 5}
В задачах на операции с массивами: сложение, вычитание, умножение и деление — вас именно об этом и просят. Точно помню, было время, когда мне сложно было понять, чего от меня требуется.

Немного объясню листинг #13. Сначала создаётся два одномерных массива, эти массивы именуются именами: A и B. Эти объявленные массивы инициализируются значениями, указываемыми в фигурных скобках. Получается два массива с конкретными значениями. Эти значения складываются между собой. Каждое слагаемое определяется номером, индексом массива. Первый элемент одного массива складывается с первым элементом другого, второй со вторым и т. д. Чтобы не складывать каждый элемент вручную, использован циклический обход по всем элементам массивов. Для того, чтобы сохранять результаты, был добавлен ещё один массив, названный sumAB. Элементы A[1] и B[1] сложились и сохранились в sumAB[1], A[2] и B[2] сложились и сохранились в sumAB[2]. Вот и вся премудрость. Сохранённое значение сразу выводится на экран.
  • Задача: Получить сумму всех элементов массива.

Чтобы правильно считать сумму, обязательно нужно переменную, сохраняющую промежуточные результаты, в самом начале инициализировать нулём. Без инициализации нулём результирующей переменной правильный результат может сложиться неизвестно с чем. Будьте внимательны.
Нужно различать задачи и понимать, что вам действительно нужно. Вот приведено две задачи, обе на сумму элементов, но одна требует сложить все элементы массивов поиндексно (листинг #13), а другая просто сложить все элементы массива между собой (листинг #14). Вроде бы условия так похожи, а результаты вон насколь разные.
Бывает необходимость задания значений в массив с клавиатуры. Пока что во всех примерах значения в массив записывались сразу из исходного кода. Запись значений с клавиатуры требует обхода всего массива с указанием на ячейки для записи. Любой обход — всегда цикл. Всё остальное ничем не отличается от работы с обычными переменными.

Писал уже об этом, но напомню лишний раз:
  • Начинающим программистам и пришлым программистам (например, с Turbo Pascal) сложно контроллировать границы массивов. Одна из очень распространённых ошибок всех новичков — выход за пределы массива. Отсчёт в С++ ведётся с нуля!
В языке С++ массивы могут быть многомерными: двумерные, трехмерные, четырёхмерные и т. д. Мерность массивов определяется количеством квадратных скобок:

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

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

  • Имя массива это только идентификатор. По стандарту массивы имеют право приводиться к типу "указатель", при этом получаемый указатель указывает на первый элемент массива.

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

  • Несмотря на то, что имя массива можно использовать как указатель, обработка указателей и обработка массивов может происходить по-разному. Компиляторы C++ различают массивы и указатели. Сходство очень большое, но некоторые отличия вы увидите прямо сейчас:
  • Операция sizeof, применённая к массиву, вернет сколько байт выделено массиву
  • Операция sizeof, применённая к указателю, вернет размер указателя
  • Адрес указателя поменять можно
  • Адрес массива поменять нельзя
  • Значением указателя, инициализированного с помощью выражения размещения, является адрес начала этой области. Сам указатель, как объект, обладает своим собственным адресом.
К сожалению, это не всё, что имеет смысл рассказать о массивах. Но тема уже получилась достаточно объёмной, надеюсь, что очень полезной. Цель этой статьи — дать вам понять природу массивов, научить их понимать и научить использовать массивы в ваших кодах. Статья ограничена описанием самого обыкновенного массива. Описание указателя на массивы выходит за рамки этой темы.
  • В С++11 был добавлен шаблонный класс array
Если вы сможете понять синтаксис этого шаблонного класса, то вместо обычных массивов лучше используйте array

Использование массивов, по листингу #18, вообще ничем не отличается от использования обычных массивов. Отличается только способ объявления.

Хотя многомерные массивы array выглядит достаточно ужасно, но если вдруг кому надо:

Любой многомерный массив — это массив, хранящий массивы. Это в любых массивах так. В случае объявления array это просто более очевидно.
Схема объявления шаблонного класса array на первое время может быть, например, такой:
Объявить тип array и прилепить к нему угловые скобки:



Дать имя массиву:



Указать тип и количество элементов внутри угловых скобок:


Чтобы создать двумерный массив, нужно массив заворачивать в массив. Чтобы трёхмерный: массив заворачивается в массив, всё это дело заворачивается в свой массив.

=====================

  • Небольшой набор задач, способных вызывать затруднения

56 комментариев на «“Одномерный массив в C++ для начинающих”»

  1. Николай:

    Пажалуйста помогите нужно в однотипном массиве состоящего из 10ти элементов умножить первый и последний элементы но они оба равны нулю

  2. Николай:

    Привет, нужна помощь.
    Как найти сумму положительных чисел двух одномерных массивов, т.е. есть два массива, их надо объеденить в один, но при этом, отрицательные числа при сложении равны 0 ( если есть -2 и 3,то будет 0+3). Нужен код или структурная схема. Буду очень благодаен за помощь.

Добавить комментарий

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

Поиск

 
     

Случайная книга в электронном формате

https://www.litres.ru/igor-savchuk/otyavlennyy-programmist-layfhaking-iz-pervyh-ruk/?lfrom=15589587

Последние комментарии

Яндекс.Метрика