Функції. Частина 2. Функції і масиви. Передача одновимірного та багатовимірного масиву в функцію. Передача структури і класу в функцію
Дана тема базується на темі: Функції. Частина 1. Опис функції. Фактичні та формальні параметри. Передача параметрів у функцію за значенням та за адресою.
Зміст
- 1. Приклад опису функції, що отримує масив цілих чисел
- 2. Приклад передачі рядка символів у функцію
- 3. Як передати масив рядків у функцію
- 4. Приклад передачі двовимірного масиву як параметру функції
- 5. Приклад передачі у функцію тривимірного масиву чисел
- 6. Як передати структуру у функцію? Приклад
- 7. Приклад передачі в функцію керованого покажчика (^) на структуру посилального типу (ref)
- 8. Як в якості параметру функції передати об’єкт класу?
- 9. Приклад передачі структури у функцію за посиланням (не підтримується у середовищі CLR)
- Зв’язані теми
Пошук на інших ресурсах:
1. Приклад опису функції, що отримує масив цілих чисел
Для передачі масиву чисел в функцію потрібно передати покажчик на цей масив чисел.
Покажчиком на масив чисел є:
- ім’я масиву;
- адреса першого елементу масиву.
Приклад. Нехай потрібно описати функцію SumArrayInts(), що отримує масив з цілих чисел і знаходить суму елементів цього масиву. Функція отримує 2 параметри:
- масив цілих чисел;
- кількість елементів у масиві.
Спосіб 1. Передача масиву як int A[].
// Функція, що підраховує суму елементів масиву цілих чисел // Функція отримує 2 параметри: // n - кількість елементів масиву, // A - масив цілих чисел int SumArrayInts(int n, int A[]) { int i; int sum = 0; // сума for (i=0; i<n; i++) sum = sum + A[i]; return sum; }
Спосіб 2. Передача масиву як int *A.
int SumArrayInts(int n, int *A) // масив передаєтсья як *A { int i; int sum = 0; // сума for (i=0; i<n; i++) sum = sum + A[i]; return sum; }
Виклик функції SumArrayInts() з іншого програмного коду.
// передача масиву у функцію int M[5] = { 23, -2, -1, -8, 4 }; int n = 5; int summa; summa = SumArrayInts(n, M); // summa = 16 summa = SumArrayInts(n, &M[0]); // теж добре, summa = 16
Слід зауважити, що при такій передачі масиву у функцію, елементи масиву можна змінювати в тілі функції.
2. Приклад передачі рядка символів у функцію
Рядок символів є масивом елементів типу char. Тому, передача рядка символів у функцію в якості параметру виконується так само як і у випадку з числами (п. 1).
Рядок символів можна передавати у функцію двома способами:
- як char*;
- як char[].
Приклад. Функція, що повертає кількість символів ‘+’ (плюс) в рядку. Ознакою кінця рядка є символ ‘\0’. Тому не потрібно передавати у функцію довжину рядка.
Спосіб 1. Визначення функції GetNPlus(). Передача рядка як char *.
// Функція, що повертає кількість символів '+' в рядку int GetNPlus(char *s) { char *s2; int n = 0; // кількість символів - результат s2 = s; while (*s2!='\0') { if (*s2=='+') n++; s2++; } return n; }
Заголовок вищенаведеної функції можна було визначити як
int GetNPlus(char s[]) { ... }
Спосіб 2. Визначення функції GetNPlus2(). Використання індексів для доступу до символів рядка.
// доступ до символів рядка за індексом int GetNPlus2(char *s) { int i=0; int n=0; while (s[i]!='\0') { if (s[i]=='+') n++; i++; } return n; }
Виклик функції GetNPlus2() з іншого програмного коду.
// передача масиву у функцію char * str = "+Test + + +++ string ."; int n; n = GetNPlus2(str); // n = 6
3. Як передати масив рядків у функцію
Приклад. Функція, що отримує масив рядків та сортує його методом вставки. Масив рядків отримується першим параметром. Другим рядком отримується кількість рядків.
// функція, що отримує масив рядків і сортує його методом вставки void SortStrings(char * s[], int n) { int i, j, k; char * ts; // допоміжна змінна for (i=0; i<n-1; i++) for (j=i; j>=0; j--) { if (strcmp(s[j],s[j+1])>0) { // обмін покажчиків на рядки місцями ts = s[j]; s[j] = s[j+1]; s[j+1] = ts; } } // на виході - посортований масив покажчиків s return; }
У вищенаведеній функції використано функцію strcmp(). Ця функція порівнює 2 рядки s1 та s2 в лексикографічному порядку:
n = strcmp(s1, s2);
і повертає значення
- >0, якщо рядок s1 слідує після рядка s2 в лексикографічному порядку;
- =0, якщо рядки рівні;
- <0, якщо рядок s1 слідує перед рядком s2 в лексикографічному порядку.
Виклик функції з іншого програмного коду:
// передача масиву покажчиків у функцію char * str[] = { "DEF", "FEC", "CSE", "AFE", "QER" }; int n = 5; int i; // виклик функції SortStrings(str, n);
4. Приклад передачі двовимірного масиву як параметру функції
У даному прикладі описана функція, що знаходить суму елементів двовимірного масиву. Функція, яка отримує двовимірний масив дійсних чисел в якості параметру.
// функція обчислення суми елементів двовимірного масиву double Sum2(double A[][3]) { double s = 0; int i,j; for (i=0; i<2; i++) for (j=0; j<3; j++) s = s + A[i][j]; return s; }
Виклик функції з програмного коду. У функцію передається двовимірний масив з іменем M розміром 2*3.
// Передача двовимірного масиву як параметру функції // двовимірний масив чисел double M[][3] = { { 2.78, -3.18, 9.4 }, { -3.4, 8.8, 0.5 } }; double summa; summa = Sum2(M);
5. Приклад передачі у функцію тривимірного масиву чисел
У даному прикладі описується функція Sum3(), яка отримує вхідним параметром тривимірний масив цілих чисел. Розмір масиву 2*3*4. Функція повертає суму елементів масиву.
// передача тривимірного масиву D як параметру функції // функція обчислює суму елементів тривимірного масиву int Sum3(int D[][3][4]) { int summa = 0; // змінна - результат int i, j, k; // обчислення суми for (i=0; i<2; i++) for (j=0; j<3; j++) for (k=0; k<4; k++) summa = summa + D[i][j][k]; return summa; }
Виклик функції з іншого програмного коду
// тривимірний масив чисел int A[2][3][4]; int i, j, k; int sum; // заповнення масиву A довільними значеннями for (i=0; i<2; i++) for (j=0; j<3; j++) for (k=0; k<4; k++) A[i][j][k] = i+j+k; // виклик функції, що знаходить суму елементів масиву sum = Sum3(A);
6. Як передати структуру у функцію? Приклад
В якості параметру структуру можна передавати у функцію трьома способами:
- за значенням;
- за адресою;
- за посиланням (не підходить для середовища CLR).
Більш детально про способи передавання параметрів у функцію описується тут.
При передаванні структури за значенням робиться копія в стеку усіх полів структурної змінної.
При передаванні структури за адресою передається тільки адреса структури в пам’яті (покажчик на структуру). Цей посіб є більш ефективним коли для полів структури потрібно виділяти багато пам’яті (розмір покажчика може бути набагато менше розміру структурної змінної).
Покажчик на структуру, який передається у функцію може бути двох типів:
- некерований покажчик (*);
- керований покажчик (^). У цьому випадку структура повинна оголошуватись з ключовим словом ref (див. п. 7).
Приклад. Передавання структурної змінної (об’єкту) за значенням та за адресою (випадок некерованого покажчика *).
Нехай за межами класу (або в іншому модулі) задано структуру, що описує точку на координатній площині:
... // структура типу struct MyPoint struct MyPoint { int x; int y; }; ...
Нехай задано 2 функції, які визначають чи точки є рівні між собою:
- функція Equals(), яка в якості параметрів отримує 2 структурні змінні типу MyPoint (передавання за значенням);
- функція EqualsP(), яка отримує 2 покажчики на структурні змінні типу MyPoint (передавання за адресою).
// функція, що визначає чи точки є рівні між собою // передавання структурних змінних здійснюється за значенням bool Equals(MyPoint mp1, MyPoint mp2) { bool f = false; if ((mp1.x==mp2.x) && (mp1.y==mp2.y)) f = true; return f; } // функція, аналогічна функції Equals, тільки // передавання структурних змінних виконується за адресою bool EqualsP(MyPoint *mp1, MyPoint *mp2) { bool f = false; if ((mp1->x == mp2->x) && (mp1->y = mp2->y)) f = true; return f; }
Тоді виклик функцій Equals() та EqualsP() можна здійснити з іншого програмного коду приблизно таким чином:
... // передавання структури у функцію MyPoint p1, p2; // структурні змінні bool res; // заповнення значення змінної p1 p1.x = 28; p1.y = -33; // заповнення значення змінної p2 p2.x = 28; p2.y = -33; // передавання структури у функцію Equals за значенням res = this->Equals(p1, p2); // res = true res = Equals(p1, p2); // res = true - також добре // передавання адреси структурної змінної res = EqualsP(&p1, &p2); // res = true ...
7. Приклад передачі в функцію керованого покажчика на структуру посилального типу (ref)
У даному прикладі продемонстровано передачу у функцію керованого (^) покажчика на структуру. Функція EqualsPRef() отримує два керовані (^) покажчики на структуру типу MyPoint. Функція визначає рівність полів структур, на які вказують покажчики.
Структура MyPoint має наступний опис:
ref struct MyPoint { int x; int y; };
Визначення (реалізація) функції EqualsPRef():
// Функція, що отримує на вході два керовані покажчики (^) // на структури посилального типу. // Функція визначає рівність структур, на які вказують покажчики bool EqualsPRef(MyPoint ^p1, MyPoint ^p2) { bool f = false; if ((p1->x == p2->x) && (p1->y == p2->y)) f = true; return f; }
Виклик функції EqualsPRef() з іншого програмного коду (наприклад, обробника події кліку на кнопці):
// якщо структура оголошена як посилальний тип // з ключовим словом ref MyPoint ^mp1; // керований покажчик на структуру MyPoint ^mp2; // виділення пам'яті під структурні змінні mp1 = gcnew MyPoint; mp2 = gcnew MyPoint; // заповнення полів структури 1 mp1->x = 30; mp1->y = -30; // заповнення полів структури 2 mp2->x = 28; mp2->y = -30; // визначення результату, виклик функції bool res; res = EqualsPRef(mp1, mp2); // res = false
8. Як в якості параметру функції передати об’єкт класу?
Нехай дано клас MyPointClass, що описує координати точки на площині. Клас описаний у двох модулях:
- в модулі MyPointClass.h описується опис функцій та полів класу;
- в модулі MyPointClass.cpp описується реалізація методів та полів класу.
Текст модуля MyPointClass.h:
#pragma once // клас оголошено як "managed" - керований ref class MyPointClass { int x; int y; public: MyPointClass(void); int GetX(void); int GetY(void); void SetXY(int nx, int ny); };
Текст модуля MyPointClass.cpp:
#include "StdAfx.h" #include "MyPointClass.h" MyPointClass::MyPointClass(void) { x = 0; y = 0; } int MyPointClass::GetX(void) { return x; } int MyPointClass::GetY(void) { return y; } // встановити нове значення x та y void MyPointClass::SetXY(int nx, int ny) { x = nx; y = ny; }
Нехай в головному модулі програми (наприклад, клас форми) описана функція EqualsClass(), що порівнює поля класу MyPointClass. Функція отримує два параметри – керовані покажчики на клас. Передати клас як параметр-значення не вдасться, оскільки клас належить до посилального типу. З класом потрібно використовувати керовані покажчики (^).
Більш детально про керовані та некеровані покажчики описується тут.
// функція, що отримує змінну-покажчик на клас як параметр // функція порівнює на рівність поля класу bool EqualsClass(MyPointClass ^p1, MyPointClass ^p2) { int x1, y1, x2, y2; bool res = false; x1 = p1->GetX(); y1 = p1->GetY(); x2 = p2->GetX(); y2 = p2->GetY(); if ((x1==x2) && (y1==y2)) res = true; return res; }
Виклик функції EqualsClass() з іншого програмного коду (наприклад, з обробника події):
// передача класу у функцію MyPointClass pc1; // об'єкт змінна типу клас, у функцію як параметр передавати неможна MyPointClass ^pc2 = gcnew MyPointClass(); // керований покажчик на клас - можна передавати у функцію MyPointClass ^pc3 = gcnew MyPointClass(); // керований покажчик на клас bool f; // встановлення значень змінних pc1.SetXY(4, 2); pc2->SetXY(5, 2); pc3->SetXY(5, 2); f = EqualsClass(pc2, pc3); // f = true, працює
Щоб використати методи класу, потрібно попередньо підключити модуль MyPointClass.h:
#include "MyPointClass.h"
9. Приклад передачі структури у функцію за посиланням (не підтримується у середовищі CLR)
Структуру можна передавати у функцію за посиланням. Нижче наведено програмний код оголошення структури MyPoint, що передається у функцію EqualsR() за посиланням для додатку типу Win32. Для додатків, що працюють у середовищі CLR такий спосіб передачі параметру не підтримується.
struct MyPoint { int x; int y; }; // передача за посиланням bool EqualsR(MyPoint& mp1, MyPoint& mp2) { bool res = false; if ((mp1.x == mp2.x) && (mp1.y == mp2.y)) res = true; return res; };
Використання функції EqualsR() в іншому програмному коді:
bool res; MyPoint p1, p2; p1.x = 23; p1.y = 23; p2.x = 26; p2.y = 23; res = EqualsR(p1, p2); // res = false
Зв’язані теми
- Функції. Опис функції. Фактичні та формальні параметри. Передача параметрів у функцію за значенням та за адресою
- Масиви. Визначення масиву. Одновимірні масиви. Ініціалізація масиву
- Масиви. Двовимірні масиви. Масиви рядків. Багатовимірні масиви
- Покажчики. Загальні поняття. Типи покажчиків. Керовані та некеровані покажчики. Покажчик на функцію. Приклади використання
- Покажчики. Некеровані покажчики і масиви. Покажчик на структуру. Покажчик на клас
- Структури. Складені типи даних. Шаблон структури. Структурна змінна. Структури в середовищі CLR. Оголошення та ініціалізація структурної змінної
- Структури. Виділення пам’яті для структури. Вкладені структури. Масиви native-структур