2025-04-15 06:04:21

Урок 11. Массивы

Чаще всего программы обрабатывают не одиночные данные, а с наборы данных. Для хранения таких наборов в языке Си используются массивы. Массив представляет собой набор однотипных значений. Объявление массива выглядит следующим образом:

тип_переменной название_массива [длина_массива]

После типа переменной идет название массива, а затем в квадратных скобках размер массива - максимальное количество значений, которое можно поместить в массив.

Важно !!! Все элементы массива располагаются в памяти подряд !!!

Каждый элемент массива имеет свой номер, который называется индексом. По этому индексу можно обращаться к отдельным элементам. Например:

#include <stdio.h>
 
int main(void)
{
    int numbers[4];
    numbers[0] = 1;
    numbers[1] = 2;
    numbers[2] = 3;
    numbers[3] = 4;
     
    printf("numbers[0] = %d \n", numbers[0]);   // 1 - первый элемент
    printf("numbers[2] = %d \n", numbers[2]);   // 3 - третий элемент
    return 0;
}

Важно !!! Нумерация элементов начинается с нуля, поэтому первый элемент массива имеет индекс 0, а не 1 - numbers[0] !!!

Язык Си позволяет сразу объявить и инициализировать массив значениями. Для этого применяется инициализатор - набор значений в фигурных скобках. При этом размер массива можно явно не указывать, так как он будет вычисляться исходя из количества элементов в инициализаторе:

int numbers[] = { 1, 2, 3, 5 };

Также, можно инициализировать не все элементы, но в этом случае следует указывать размер массива:

int numbers[5] = { 10, 12}; // 10, 12, 0, 0, 0

Можно инициализировать значения не по порядку:

int numbers[5] = { [1]=11, [3] = 13 };

Важно !!! Если начальные значения не заданы, то в памяти лежит мусор !!!

Размер массива можно установить динамически с помощью переменной/константы:

#include <stdio.h>
int main( void )
{
    int maxSize;
    printf ("Input num = ");
    scanf("%d", &maxSize);
    int array[maxSize];
    array[0] = 1;
    array[1] = 2;
    array[2] = 3;
    for (int i = 0; i < maxSize; i++)
    {
        printf ("%d = %d\n", i, array[i]);
    }
    return 0;
}

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

const int numbers[3] = {11, 12, 13};

Многомерные массивы

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

int numbers[3][2] = { {1, 2}, {4, 5}, {7, 8} };

Здесь массив numbers имеет три элемента (3 строки), а каждый из этих элементов сам представляет массив из двух элементов (2 столбцов). 

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

int numbers[3][2] = { 1, 2, 4, 5, 7, 8 };

Для перебора многомерного массива используются вложенные циклы. Общее количество циклов равно мерности массива. Пример перебора двумерного массива:

#include <stdio.h>
 
int main(void)
{
    int numbers[3][2] = { {1, 2}, {4, 5}, {7, 8} };
    // проходим по 3 строкам таблицы
    for(int i = 0; i < 3; i++)
    {
        // проходим по 2 столбцам каждой строки
        for(int j = 0; j < 2; j++)
        {
            printf("numbers[%d][%d] = %d \n", i, j, numbers[i][j]);
        }
    }
    return 0;
}
Стоит отметить, что массивы - это фактически абстракция, которая в реальности не существует. В реальности все массивы являются одномерными и представляют сплошной блок памяти. Возможно, гораздо удобнее работать, скажем, с табличными данными как с двухмерных массивом. Однако мы могли бы инициализировать многомерные массивы как одномерные:

Размер и количество элементов массива

Для того, чтобы узнать размер массива, можно использовать оператор sizeof, который возвращает размер всего массива в байтах в виде значения типа size_t:

#include <stdio.h>
int main( void )
{
    int numbers[] = { 5, 6, 7};
    size_t size = sizeof(numbers);
    size_t count = sizeof(numbers) / sizeof(numbers[0]);
    printf("numbers size: %zu \n", size);     // numbers size: 12
    printf("count: %zu \n", size);           // count: 12
    return 0;
}

Так как size_t фактически является псевдонимом для типа unsigned long long, то есть 64-разрядное положительное число, то для его вывода на консоль применяется спецификатор %zu.

Количество элементов в массиве можно вычислить разделив размер всего массива на размер одного элемента:

size_t count = sizeof(numbers) / sizeof(numbers[0]);

Сортировка пузырьком

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

сортировка пузырьком

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

#include <stdio.h>

#define MAX_SIZE 5

int Input(int* arr, int n)
{
    int i;
    for(i=0; i < n; i++)
        scanf("%d",&arr[i]);
    return i;
}

void Print(int *arr,int len)
{
    int i;
    for (i = 0; i < len; i++)
    printf("%d ",arr[i]);
    printf("\n");
}

void SwapArr(int *arr,int i,int j)
{
    int temp = arr[i];
    arr[i]   = arr[j];
    arr[j]   = temp;
}

void BubbleSort(int* arr,int n)
{
   int noSwap;
   for (int i = 0; i < n; i++)
   {
      printf("%d\n",i);
      noSwap = 1;
      for (int j = n-1; j > i; j--)
      {
        if( arr[j - 1] > arr[j] )
        {
          SwapArr(arr,j-1,j);
          noSwap = 0;
        }
      }
        if(noSwap)
          break;
    }
}

int main( void )
{
  int arr[MAX_SIZE];
  Input(arr, MAX_SIZE);
  BubbleSort(arr, MAX_SIZE);
  Print(arr, MAX_SIZE);
  return 0;
}

В константе MAX_SIZE устанавливается размер массива, функция Input получает значения элементов массива, функция BubbleSort осуществляет сортировку, функция Print выводит значения элементов на консоль. Функция SwapArr является вспомогательной и просто меняет элементы местами.

Комментарии ()