Вернуться наверх
aco.ifmo.ru photonic
вернуться в оглавление предыдущая глава предыдущий параграф следующий параграф следующая глава


3.1. Массивы

3.1.1. Одномерный массив

Массив — это группа последовательных ячеек памяти, имеющих один и тот же тип. Чтобы обратиться к определенной ячейке, или элементу массива, мы используем имя массива и индекс (номер) элемента в массиве. При описании задается количество элементов в массиве в квадратных скобках, и дальнейший доступ к элементам массива осуществляется с помощью оператора []. Нумерация элементов массива начинается с 0, т.е. если в массиве 4 элемента, номера элементов будут от 0 до 3:

int data[4]; // описание массива из 4 элементов 

// инициализация элементов массива, обращение к элементам массива по индексу 
data[0]=1; 
data[1]=2; 
data[2]=3; 
data[3]=4; 

Возможна инициализация массива при объявлении в фигурных скобках, в этом случае указывать количество элементов в массиве не обязательно, компилятор определит это их сам:

// массив из трех элементов 0-го, 1-го, 2-го. Элементы нумеруются от 0 до размер-1 
double v[3]={0.3, 2.2, 2.}; 

// количество элементов указывать не обязательно 
char symbols[]={'a', 'b', 'c', 'd', 'e'};

3.1.2. Динамическое размещение одномерного массива

Массивы с небольшим количеством элементов легко размещаются в статической памяти программы. Но для массивов с большим количеством элементов намного эффективнее будет динамическое размещение (а для массивов с очень большим количеством элементов это необходимо, так как размер сегмента данных ограничен). В этом случае объявляется указатель на массив, а затем при помощи ключевого слова new выделяется память для требуемого количества элементов. Далее при работе с массивом доступ к элементам массива осуществляется одинаково, независимо от того как он размещен в памяти. Если массив размещается динамически, в конце программы обязательно нужно освободить память при помощи оператора delete.

double *data; // указатель на массив
data=new double[1000]; // указатель на 0-й элемент массива

// инициализация
// после размещения в массиве "мусор" и сразу обязательно инициализировать все его элементы
for(int i=0; i<1000; i++)
{
   data[i]=0.;
}

delete [] data; // обязательно освободить память 

data+1; // указатель на 1-й элемент
data+100; // указатель на 100-й элемент, 
*(data+4); // эквивалентно data[4]

3.1.3. Передача массива в функцию (пример 3.1)

Передача массива в функцию может осуществляться только по указателю на нулевой элемент, с дополнительной информацией о количестве элементов в массиве:

/////////////////////////////////////////////////////////////////////////////
// Прикладное программирование
// Пример 3.1. Пример работы с динамическим одномерным массивом
// 
// Кафедра Прикладной и компьютерной оптики, http://aco.ifmo.ru
// Университет ИТМО
/////////////////////////////////////////////////////////////////////////////
// подключение библиотеки ввода-вывода
#include <iostream>
// подключение стандартного пространства имен для использования библиотек
using namespace std;

// прототипы функций 
double sum(double data[], int n);
/////////////////////////////////////////////////////////////////////////////
// пример передачи массива в функцию
// функция вычисляет сумму всех элементов массива
// data - массив (указатель на 0-й элемент массива)
// n - количество элементов в массиве
double sum(double data[], int n)
{
    double sum=0.;
    for(int i=0; i<n; ++i)
    {
        sum+=data[i];
    }
    return sum;
}
/////////////////////////////////////////////////////////////////////////////
void main()
{
    // объявление указателя на массив
    double *data; 
    int count=1000; // количество элементов в массиве
    // динамическое размещение массива, data - указатель на 0-й элемент массива
    data=new double[count]; 

    // вывод 10 элементов массива до инициализации (в массиве "мусор")
    for(int i=0; i<10; i++)
    {
        cout<<data[i]<<endl;
    }
    cout<<"-----------------"<<endl;

    // инициализация массива
    for(int i=0; i<count; i++)
    {
        data[i]=i;
    }

    // вывод 10 элементов массива после инициализации
    for(int i=0; i<10; i++)
    {
        cout<<data[i]<<endl;
    }
    cout<<"-----------------"<<endl;

    cout<<data<<endl;      // указатель на 0-й элемент
    cout<<data+1<<endl;    // указатель на 1-й элемент
    cout<<*(data+4)<<endl; // эквивалентно data[4]
    cout<<data[count-1]<<endl; // последний элемент массива
    cout<<"-----------------"<<endl;

    // пример передачи массива в функцию
    cout<<sum(data, count)<<endl;
    cout<<sum(&data[0], count)<<endl;
    cout<<"-----------------"<<endl;

    delete [] data; // обязательно освободить память 

    cout<<data[4]<<endl; // ОШИБКА! ссылка на уже несуществующий элемент массива
}
/////////////////////////////////////////////////////////////////////////////

3.1.4. Двумерный массив

Для создания двумерного массива необходимо указать в квадратных скобках два значения – количество строк и столбцов в массиве.

 тип_массива имя_массива[кол-во строк][кол-во столбцов]; 

Рисунок иллюстрирует индексы элементов двумерного массива. Массив содержит три строки и два столбца.

[0][0]

[0][1]

[1][0]

[1][1]

[2][0]

[2][1]

На самом деле, в памяти двумерные массивы хранятся по строкам, как показано на рисунке:

[0][0]

[0][1]

[1][0]

[1][1]

[2][0]

[2][1]

 

double matrix[3][2]; // двумерный массив 2х3 

double sum=0.;
for(int i=0; i<3; i++) // номер строки
{
    for(int j=0; j<2; j++) // номер столбца
    {
        sum+=matrix[i][j];
    }
} 

3.1.5. Динамическое размещение двумерного массива (пример 3.2)

Двумерный массив можно разместить динамически, только если представить его как одномерный. В этом случае вместо доступа по индексам [ i][ j], придется вычислять индекс одномерного массива, которому будет соответствовать необходимый элемент двумерного массива.

Например, если двумерный массив 3х2 разместить как одномерный, элементу [1][0] двумерного массива будет соответствовать индекс [2] одномерного массива.

0

1

2

3

4

5

[0][0]

[0][1]

[1][0]

[1][1]

[2][0]

[2][1]

 

/////////////////////////////////////////////////////////////////////////////
// Прикладное программирование
// Пример 3.2. Пример работы с динамическим двумерным массивом
// 
// Кафедра Прикладной и компьютерной оптики, http://aco.ifmo.ru
// Университет ИТМО
/////////////////////////////////////////////////////////////////////////////
// подключение библиотеки ввода-вывода
#include <iostream>
// подключение стандартного пространства имен для использования библиотек
using namespace std;

/////////////////////////////////////////////////////////////////////////////
void main()
{
    // динамическое размещение массива 3х2 
    double *matrix=new double[3*2]; 

    // инициализация массива
    for(int j=0; j<2; j++) // номер столбца
    {
        for(int i=0; i<3; i++) // номер строки
        {
            matrix[i*2+j]=j*10+i;
        }
    } 

    // вывод элементов массива на экран
    for(int j=0; j<2; j++) // номер столбца
    {
        for(int i=0; i<3; i++) // номер строки
        {
            cout<<matrix[i*2+j]<<" ";
        }
        cout<<endl;
    }    

    delete [] matrix; //освободить память
}
/////////////////////////////////////////////////////////////////////////////