Одномерные массивы
Хранение данных
Предположим, что вы разработали компьютерную игру под названием "Враждебный пользователь", в которой игроки состязаются с замысловатым и недружественным компьютерным интерфейсом. Теперь вам необходимо написать программу, которая отслеживает ежемесячные объемы продаж этой игры в течение пятилетнего периода. Или, скажем, вам нужно провести инвентаризацию торговых карт героев-хакеров.
Очень скоро вы придете к выводу, что для накопления и обработки информации вам требуется нечто большее, чем простые базовые типы. Язык Си предлагает это нечто большее, а именно — составные типы.
 
Составные типы - это типы, состоящие из базовых целочисленных типов и типов с плавающей точкой.

Массив, например, может хранить множество значений одного и того же типа. Отдельный вид массива может хранить строки, которые являются последовательностями символов.
Структуры могут хранить по нескольку значений разных типов. Кроме того, есть еще указатели, которые представляют собой переменные, сообщающие компьютеру местонахождение данных в памяти.
Все эти составные формы данных цель нашего изучения.
 
Массивы. Введение
Массив – это группа ячеек памяти одинакового типа, расположенных рядом и имеющих общее имя. Каждая ячейка в группе имеет уникальный номер.

Например, массив может содержать 60 значений типа int, которые представляют информацию об объемах продаж за 5 лет, 12 значений типа short, представляющих количество дней в каждом месяце, или 365 значений типа float, которые указывают ежедневные расходы на питание в течение года. Каждое значение сохраняется в отдельном элементе массива, и компьютер хранит все элементы массива в памяти последовательно — друг за другом.

При работе с массивами необходимо научиться решать три задачи:
• выделять память нужного размера под массив;
• записывать данные в нужную ячейку;
• читать данные из ячейки.
 
1) Объявление массива
Чтобы использовать массив необходимо его объявить - выделить место в памяти.
При объявлении массива мы должны указать:
• тип значений каждого элемента;
• имя массива;
• количество элементов в массиве.
int A[10], B[20]; // 2 массива на 10 и 20 целых чисел
float C[12]; // массив из 12 вещественных чисел

Общая форма объявления массива
Тип_Элементов имя_Массива[размер_Массива];

Для повышения универсальности программы размер массива лучше определять через константу. В этом случае изменить программу для массива другого размера достаточно легко, необходимо будет только поменять значение этой константы.
#include <iostream>
using namespace std;
main()
{
  const int Nmax = 20;   // константа, определяющая размер массива
  int A[Nmax];   // размер массива задан через константу
  ... 
} 

В таблице показаны примеры правильного и неправильного объявления массива.
 
Правильно Неправильно
int A[20];
размер массива указан явно
int A[];
размер массива неизвестен
const int N = 20;
int A[N];
размер массива –
постоянная величина
int N = 20;
int A[N];

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

Иногда необходимо вводить размер массива с клавиатуры. В этом случае в программе нужно заранее выделить в памяти массив наибольшего размера, соответствующее условию задачи. Это очень часто применяется в автоматических системах проверки задач, таких как silvertests.ru.
В этом случае объявление массива можно оформить следующим образом:
 
#include<iostream>
using namespace std;
main()
{
  const int Nmax = 100; // Выделяем место в памяти под максимально возможный размер массива 
                       // (обычно это значение указано в условии задачи). 
  int A[Nmax], N; 
  cin >> N; // Рабочее число элементов массива задаем с клавиатуры. 
            // Это позволяет проверить работу программы на массивах разной длины.
  ... 
} 

Обращение к элементу массива

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

ЗАПОМНИТЕ!
НУМЕРАЦИЯ МАССИВОВ В СИ НАЧИНАЕТСЯ С НУЛЯ.

(Это является обязательным — вы должны начинать с нуля. Это особенно важно запомнить)

Примеры обращения к массиву A:
x = (A[3] + 5)*A[1]; // прочитать значения A[3] и A[1]
A[0] = x + 6; // записать новое значение в A[0]
Разберем программу работы с элементами массива.
#include <iostream>
using namespace std;
main()
 {
   int i=1, A[5]; 
   A[0] = 23;  //в каждый из 5 элементов массива (индексы от 0 до 4)
   A[1] = 12;  //записываем определенное значение
   A[2] = 7;   
   A[3] = 43;
   A[4] = 51;
   A[2] = A[i] + 2*A[i-1] + A[2*i]; //изменим значение элемента с индексом 2, на результат выражения
                                    //т.к i=1, то подставляя значение переменной i в выражение получим
                                    //следующее выражение  A[2] = A[i] + 2*A[0] + A[2];
   cout << A[2]+A[4];
}
В результате выполнения данной программы на экране появится значение элемента массива с индексом 2 равное 116 Как видно из примера, мы можем обращаться к любому элементу массива. А также вычислять необходимый номер элемента по различным формулам (например, как в программе A[i-1] или A[2*i], в данных случаях индексы элементов будут вычислены и зависят от значения i.)

Разберем пример программы
#include<iostream>
using namespace std;
main()
{
  const int N = 5; 
  int A[N]; 
  x = 1;
  cout << A[x-3];   //обращение к элементу A[-2]
  A[x+4]=A[x]+A[2*(x+1)];  //после подстановки х в выражения и вычислений получаем следующую строку: A[5] = A[1]+A[4];
  ... 
} 

Т.к. массив объявлен из 5 элементов, значит элементы будут иметь нумерацию с 0 до 4. Видим что, программа обращается к несуществующим элементам: A[-2] и A[5]
Получается, что программа вышла за границы массива

Выход за границы массива - это обращение к элементу с индексом, который не существует в массиве.

В таких случая программы обычно завершается аварийно с ошибкой run-time error

Давайте попробуем самостоятельно поработать с элементами массива. Выполните задание
 

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

Для этого используется чаще всего цикл с переменной, которая изменяется от 0 до N-1 (N количество элементом массива).
...
const int N = 10;
int A[N]; 
for (i = 0; i < N; i++)
  {
     // действие над элементом A[i] 
  }
...
В указанном цикле переменная i будет принимать значения 0, 1, 2, ..., N-1.  То есть на каждом шаге цикла мы обращаемся к конкретному элементу массива с индексом i.
Таким образом, достаточно записать, что нужно сделать с одним элементом массива A[i] и эти действия поместить внутрь такого цикла.
 
Задача
Заполнить массив первыми N натуральными числами. Т.е. по окончанию программы элементы массива должны стать равными:
A[0] = 1; 
A[1] = 2;
A[2] = 3;
...
A[N-1] = N;

Нетрудно заметить закономерность: значение элемента массива должно быть больше на 1, чем индекс элемента.
Цикл будет выглядеть следующим образом:
for (i=0; i<N; i++)
{
   A[i] = i+1; 
}