Добрый вечер друзья. Продолжаем изучать работу с массивами и указателями.
Сегодня научимся передавать массив в функцию и возвращать массив из функции.
Итак, начнем с первого пункта. Пусть нам необходимо передать массив в функцию и там его обработать. Ну допустим вывести его элементы на экран. Тут возможны два варианта.
1. У нас статический массив.
2. У нас динамический массив.
В зависимости от этого и нужно плясать.
Первый случай. Передача в функцию статического массива.
Для определенности будем передавать массив символов. Напишем функцию, которая принимает строку и выводит её на экран.
Листинг 18.1
Давайте внимательно рассмотрим аргументы, которая эта функция принимает. Первый из них как раз и есть массив, который мы хотим передать. Как видите отличие от передачи обычной переменной лишь в том, что мы после имени пишем квадратные скобки. Именно они и указывают на то, что это не просто некая переменная а целый массив переменных данного типа.
В скобках, не нужно указывать размерность массива. С размерностью массива вообще все не так просто. Функции в Си не умеют самостоятельно определять размерность переданного им массива. Поэтому отдельным параметром нам необходимо передавать его размер. В нашей функции мы передаем размер массива с помощью переменной n.
Напишем самую простую программу, которая будет использовать эту функцию.
Листинг 18.2
Обратите внимание, что передача массива в функцию в этом случае, по виду, ничем не отличается от передачи обычной переменной. Мы лишь указываем его имя и все. Это только на первый взгляд так кажется. Но об этом чуть позже.
Второй случай. Передача в функцию динамического массива.
Давайте решим такую задачу. имеется текстовый файл input.txt. Пусть в нем в первой строчке записано натуральное число N не превосходящее 100. А в следующих N строках записаны некоторые вещественные числа. Пусть мы хотим посчитать среднее арифметическое всех этих чисел и вывести.
Удобно для хранения чисел завести динамический массив. Хотя, на самом деле, в этой задаче мы могли бы просто читать числа из файла и сразу вычислять их среднее значение. Но как-то я не могу придумать пока более подходящего примера.
И так напишем требуемую программу.
Листинг 18.3
Обратите внимание на аргументы функции. Как видите, если мы передаем динамический массив, то нам нужно явно указывать на то, что функция принимает указатель на первый элемент массива. В случае одномерного массива это не критично, и вы можете объявить аргументы как и в прошлый раз, т.е.
void sa_arr(float a[], int n)
но так делать не стоит. Приучайтесь сразу передавать динамические массивы таким образом.
Теперь вернемся к нашим отличиям а так же второму вопросу.
Если вы помните, то переменные в языке Си, при передаче их в функцию передаются по значению. То есть мы передаем не сами переменные, а только их значения. И если мы в функции будем их изменять, то настоящих переменных это никак не коснется. В нашей группе в вк, даже было небольшое задание на эту тему. Да и в уроке с указателями мы разбирали, как обойти это ограничение.
Основное отличие передачи массива в функцию в том, что массивы, в отличие от переменных всегда передаются по ссылке. Т.е. в функцию передается не копия массива, а сам массив. И если внутри функции мы будем как-то изменять массив, то эти изменения останутся и после того, как функция закончит свою работу.
Несколько изменим наше предыдущую программу. Изменим один из элементов внутри функции. И посмотрим, что будет с исходным массивом.
Листинг 18.4
Результат работы программы на следующем рисунке.
Как видите, изменения массива внутри функции, затронуло и исходный массив.
Эту возможность следует использовать во благо. А именно для того, чтобы возвращать массив из функции. Т.е. мы даже не будем париться над тем, чтобы возвращать массив из функции, он мы просто изменим его внутри и потом будем так же работать с в нашей программе ним.
Если же, по каким-то причинам, мы не хотим, чтобы элементы массива внутри функции менялись, то нам нужно внутри функции сделать копию переданного массива и работать уже с этой копией. Не забывайте, при использовании динамических массивов убираться за собой в памяти.
1. Напишите функцию, которая сортирует массив методом пузырька и выводит отсортированный массив на экран. В этом варианте программы, сделайте так, чтобы изменения не коснулись исходного массива.
2. Напишите функцию, которая ищет максимальный элемент в массиве.
3. Напишите функцию, которая принимает два массива одинаковой длинны и поэлементно перемножает их. Результат работы она записывает в элементы первого массива. Т.е. буквально она должна вернуть результат свой работы в первом массиве.
В программе, НЕ В ФУНКЦИИ, выведите результат на экран.
Если мы передаем массивы
[2,5,6]
[1,4,2]
то в результате своей работы, программа должна вывести
2 20 12
Сегодня научимся передавать массив в функцию и возвращать массив из функции.
Прочитайте улучшенную версию этого урока "Передача аргументов в функцию".
В новой версии:
- Ещё более доступное объяснение
- Дополнительные материалы
- 12 задач на программирование с автоматической проверкой решения
Итак, начнем с первого пункта. Пусть нам необходимо передать массив в функцию и там его обработать. Ну допустим вывести его элементы на экран. Тут возможны два варианта.
1. У нас статический массив.
2. У нас динамический массив.
В зависимости от этого и нужно плясать.
Первый случай. Передача в функцию статического массива.
Для определенности будем передавать массив символов. Напишем функцию, которая принимает строку и выводит её на экран.
Листинг 18.1
void print_arr(char a[], int n){
for (int i=0; i<n; i++)
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");
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