Добрый вечер друзья. Продолжаем изучать работу с массивами и указателями.

Сегодня научимся передавать массив в функцию и возвращать массив из функции.

Прочитайте улучшенную версию этого урока «Передача аргументов в функцию».

В новой версии:

  • Ещё более доступное объяснение
  • Дополнительные материалы
  • 12 задач на программирование с автоматической проверкой решения

Итак, начнем с первого пункта. Пусть нам необходимо передать массив в функцию и там его обработать. Ну допустим вывести его элементы на экран. Тут возможны два варианта.
1. У нас статический массив.
2. У нас динамический массив.

В зависимости от этого и нужно плясать.

Первый случай. Передача в функцию статического массива. 

Для определенности будем передавать массив символов. Напишем функцию, которая принимает строку и выводит её на экран.

Листинг 18.1

void print_arr(char a[], int n){
      for (int i=0; i<n; i++)
            printf(«%c»,a[i]);
      printf(«\n»);
}

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

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

Напишем самую простую программу, которая будет использовать эту функцию.

Листинг 18.2

#include <stdio.h>
#include <string.h>
void print_arr(char a[], int n){
      for (int i=0; i<n; i++)
            printf(«%c»,a[i]);
      printf(«\n»);

}
int main(){
      char arr[]=«kirill»;
      int t=strlen(arr);
      print_arr(arr,t);
      return 0;
}

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

Второй случай. Передача в функцию динамического массива.

Давайте решим такую задачу. имеется текстовый файл input.txt. Пусть в нем в первой строчке записано натуральное число N не превосходящее 100. А в следующих N строках записаны некоторые вещественные числа. Пусть мы хотим посчитать среднее арифметическое всех этих чисел и вывести.

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

И так напишем требуемую программу.

Листинг 18.3

#include <stdio.h>
void sa_arr(float *a, int n){
      double summ=0;
      for (int i=0; i<n; i++)
            summ+=a[i];
      printf(«srednee arifmeticheskoe: %.2f\n», summ/n);
}

int main(){
      freopen(«input.txt»,«r»,stdin);
      int N;
      scanf(«%d»,&N);
      float *arr = new (float [N]);
      for (int i=0; i<N; i++)
            scanf(«%f», &arr[i]);
      sa_arr(arr,N);
      delete []arr;
      return 0;
}

Обратите внимание на аргументы функции. Как видите, если мы передаем динамический массив, то нам нужно явно указывать на то, что функция принимает указатель на первый элемент массива. В случае одномерного массива это не критично, и вы можете объявить аргументы как и в прошлый раз, т.е.
void sa_arr(float a[], int n)
но так делать не стоит. Приучайтесь сразу передавать динамические массивы таким образом.

Теперь вернемся к нашим отличиям а так же второму вопросу.

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

Несколько изменим наше предыдущую программу. Изменим один из элементов внутри функции. И посмотрим, что будет с исходным массивом.

Листинг 18.4

#include <stdio.h>
void sa_arr(float *a, int n){
      double summ=0;
      for (int i=0; i<n; i++)
            summ+=a[i];
      printf(«srednee arifmeticheskoe: %.2f\n», summ/n);
      //изменим какой-нибудь элемент массива внтури функции
      a[2]=43.2;
} 


int main(){
      freopen(«D:\\input1.txt»,«r»,stdin);
      int N;
      scanf(«%d»,&N);
      float *arr = new (float [N]);
      for (int i=0; i<N; i++)
            scanf(«%f», &arr[i]);
      //выводим массив
      for (int i=0; i<N; i++)
            printf(«%f\t»,arr[i]);
      printf(«\n»);
      sa_arr(arr,N);    
      // снова выводим массив на экран, после вызова функции
      // внутри которой, мы изменили один его элемент
      for (int i=0; i<N; i++)
            printf(«%f\t»,arr[i]);
      printf(«\n»);
      delete []arr;
      return 0; 
}

Результат работы программы на следующем рисунке.

Как видите, изменения массива внутри функции, затронуло и исходный массив.
Эту возможность следует использовать во благо. А именно для того, чтобы возвращать массив из функции. Т.е. мы даже не будем париться над тем, чтобы возвращать массив из функции, он мы просто изменим его внутри и потом будем так же работать с в нашей программе ним.

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

Задание для практической работы:

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

2. Напишите функцию, которая ищет максимальный элемент в массиве.

3. Напишите функцию, которая принимает два массива одинаковой длинны и поэлементно перемножает их. Результат работы она записывает в элементы первого массива. Т.е. буквально она должна вернуть результат свой работы в первом массиве.
В программе, НЕ В ФУНКЦИИ, выведите результат на экран.

Если мы передаем массивы
[2,5,6]
[1,4,2]

то в результате своей работы, программа должна вывести
2 20 12

От KaDeaT