C#
Тема 10: «Підпрограми. Процедури та функції»
Рекурентні послідовності
Опрацювати матеріал навчальної презентації
Процедури і функції
Були такі поняття ("функції", "процедури" і "підпрограми") в більш ранніх мовах програмування.
У С# те, що я назвала процедурами і функціями є методами. Робити ООП процедурним ми не будемо, але познайомимося із даними поняттям і розглянемо деякі задачі.
Процедури і функції. відмінності
Опорний конспект (опрацювати завдання самостійно)
Функція відрізняється від процедури двома особливостями:
- завжди обчислює деяке значення, що повертається в якості результату функції;
- викликається в виразах.
Процедура C # має свої особливості:
- повертає формальний результат void, який вказує на відсутність результату, що повертається при виклику процедури; виклик процедури є оператором мови;
- має вхідні і вихідні аргументи, причому вихідних аргументів - її результатів - може бути досить багато.
Процедура - це підпрограма, яка може викликатися в коді основної програми і виробляти будь-які дії з переданими в неї змінними. Функція - це така ж процедура, тільки їй властиве явне повернення результату її роботи.
У мові C # немає спеціальних ключових слів - procedure і function, але присутні самі ці поняття. Синтаксис оголошення методу дозволяє однозначно визначити, чим є метод - процедурою або функцією.
Опис методів (процедур і функцій). синтаксис
Синтаксично в описі методу розрізняють дві частини - опис заголовка і опис тіла методу:
заголовок_методу
тіло_методу
Розглянемо синтаксис заголовка методу:
[Атрибути] [модифікатори] {void | тип_результату_функціі}
ім'я_методу ([список_формальних_аргументів])
Ім'я методу і список формальних аргументів складають сигнатуру методу. Сигнатурі не належать імена формальних аргументів, тут важливі типи аргументів. У сигнатуру не входить і тип результату, що повертається .
Зазвичай метод воліють реалізувати у вигляді функції тоді, коли він має один вихідний аргумент, що розглядається як результат обчислення значення функції. Можливість виклику функцій у виразах також впливає на вибір на користь реалізації методу у вигляді функції. В інших випадках метод реалізують у вигляді процедури.
static <тип, що повертається в основну програму> <Ім’я функції>(аргумент і його тип)
{ …
return <змінна, значення якої повертається в основну програму>
}
Запам'ятайте процедура завжди починається зі слова void, а функція з назви класу або типу, який вона повертає (наприклад string).
Процедури
<модифікатор доступу> Void <назва> (параметри)
{
тіло процедури
}
Функції
<модифікатор доступу> <тип> <назва> (параметри)
{
Тіло функції
Return <тип>;
}
<модифікатор доступу>: дозволяє бачити або приховувати процедури для їх виклику, може бути: public private. Так само існує модифікатор static.
Статичні процедури і функції (зі словом статик) постійно знаходяться в пам'яті комп'ютера і створюються при запуску програми, в той час як не статичні створюються лише під час створення екземпляра класу, до якого вони належать.
Процедури і функції потрібні для того, щоб оптимізувати код програми. Процедури дозволяють виділити повторюваний код в підпрограму і викликати її на вимогу, що дозволяє уникнути багаторазового написання повторюваного коду, а так само зменшити місце займане програмою.
Також функції і процедури дозволяють виділяти ділянки коду в логічні блоки, що допомагає, потім її швидше розбирати і розуміти, ніж читати однотипний код програми. А також в разі якщо ви виявили помилку в коді процедури (функції) її виправлення призведе до виправлення у всій програмі і не доведеться переглядати весь написаний код повторюваних шаблонів.
Повернення значень
static double getVal()
{
double checkVal;
// присвоєння checkVal значення,
// отриманого в результаті обчислень.
if (checkVal < 5)
return 4.7;
return 3.2;
}
Неправильно! А якщо умова не справджується, що вертається?!
static double getVal()
{ double checkVal;
// присвоєння checkVal значення,
// отриманого в результаті обчислень.
if (checkVal < 5)
return 4.7;
}
Звертання до підпрограми (функції)
static <Тип> <ім’яфункції>(
Опорнi задачi
1. Знайти максимум серед двох даних чисел. Скористайтеся зверненням до підпрограм.
static int Input_a() // підпрограми вводу 1 числa
{
Console.Write("a= ");
int a = int.Parse(Console.ReadLine());
return a;
}
static int Input_b() // підпрограми вводу 2 числa
{
Console.Write("b= ");
int b = int.Parse(Console.ReadLine());
return b;
}
static void Main(string[] args)
{
Console.WriteLine("Введiть пару чисел:");
//звернення до підпрограми та виведення результату
Console.WriteLine("max = {0} ", Math.Max (Input_a(),Input_b()));
Console.ReadKey();
}
2. З клавіатури вводяться кілька цілих чисел (скористатися циклом). Знайти кількість цифр у них. Скористатися процедурою. (Загальний метод - спочатку рядок перетворюємо у число, а потім у підпрограмі перетворюємо число у рядок і знаходимо його довжину). У сучасних мовах програмування число вводиться як рядок і запропонований спосіб не потрібний. Приклад подано тільки для ознайомлення із структурою програмного коду із підпрограмами (процедурами чи функціями) та звернення до них.
class Program
{
// пошуку кількості цифр у числах
static int kilk(int n)
{
string s = n.ToString();
int m = s.Length;
return m;
}
static void Main(string[] args)
{
int i;
for (int j = 0; j < 4; j++)
{
Console.WriteLine("Введiть довiльне цiле число");
i = int.Parse(Console.ReadLine());
Console.WriteLine("Кiлькiсть цифр у числi {0} - {1} ",i,kilk(i));
}
Console.ReadKey();
} }
3. Опрацюйте даний програмний код. Проаналізуйте звернення до підпрограми з основної програми та самі підпрограми вводу розмірів ділянки поля прямокутної форми
class Program
{
// підпрограми вводу даних поля
static int Input_a()
{
Console.Write("Чому дорiвнює довжина поля? ");
int a = int.Parse(Console.ReadLine());
return a;
}
static int Input_b()
{
Console.Write("Чому дорiвнює ширина поля? ");
int b = int.Parse(Console.ReadLine());
return b;
}
// основна програма (Визначаємо суму площ 3 полів)
static void Main(string[] args)
{
int s=0;
s = Input_a()*Input_b();//звернення до підпрограми
Console.WriteLine("Площа поля = {0}", s);
Console.ReadKey();
}
Дано два різні лінійні масиви. Знайти максимальний елемент першого з них та мінімальний елемент другого, використовуючи підпрограми.
class Program
{
// підпрограма пошуку максимального елементу масиву
static int MaxValue(int[] intArray)
{
int max = intArray[0];
for (int i = 1; i < intArray.Length; i++)
if (intArray[i] > max) max = intArray[i];
return max;
}
// підпрограма пошуку мінімального елементу масиву
static int MinValue(int[] intArray)
{
int min = intArray[0];
for (int i = 1; i < intArray.Length; i++)
if (intArray[i] < min) min = intArray[i];
return min;
}
// основна програма
static void Main(string[] args)
{
int[] a = {1, 8, 3, 6, 2, 5, 9, 3, 0, 2};
Console.WriteLine("Дано масив");
int n=a.Length;
for (int i = 0; i < n; i++) Console.Write(a[i]+" ");
int max = MaxValue(a);//звернення до підпрограми
Console.WriteLine();
Console.WriteLine("Максимальний елемент = {0}", max);
int[] b = { 14, 8, 12, 6, 2, 15, 9, 17, 10, 12,3 };
int min = MinValue(b);//звернення до підпрограми
Console.WriteLine("Мiнiмальний елемент = {0}", min);
Console.ReadKey();
}
} }
Приклад 2
У двох різних цілих лінійних масивах знайти: у першому - суму, у другому - добуток елементів масивів.
class Program
{
// підпрограма пошуку суми елементів масиву
static int Suma(int[] intArray)
{
int s=0;
for (int i = 0; i < intArray.Length; i++)
s=s+intArray[i];
return s;
}
// підпрограма пошуку добутку елементів масиву
static int dobutok(int[] intArray)
{
int d = 1;
for (int i = 0; i < intArray.Length; i++)
d=d*intArray[i];
return d;
}
// основна програма
static void Main(string[] args)
{
int[] a = {1, 8, 3, 6, 2, 5, 9, 3, 0, 2};
Console.WriteLine("Дано масив A:");
int n=a.Length;
for (int i = 0; i < n; i++) Console.Write(a[i]+" ");
Console.WriteLine();
int s = Suma(a);
Console.WriteLine("Сума елементiв масиву А = {0}", s);
int[] b = {1, 8, 12, 6, 2, 1, 9 };
int m=b.Length;
for (int i = 0; i < m; i++) Console.Write(b[i]+" ");
Console.WriteLine();
Console.WriteLine("Дано масив B:");
int d = dobutok(b);
Console.WriteLine("Добуток елементiв масиву В = {0}", d);
Console.ReadKey();
} } }
Приклад 3
Дано три цілочисельні масиви різної розмірності. Знайти суму елементів трьох масивів з використанням підпрограми.
class Program
{
// підпрограма пошуку суми елементів масиву
static int suma(int[] intArray)
{
int s=0;
for (int i = 0; i < intArray.Length; i++) s=s+intArray[i];
return s;
}
static void Main(string[] args)
{
int[] a = {1, 8, 3, 6, 2, 5, 9, 3, 0, 2};
int[] b = {11, 8, 12, 6, 2, 10, 9};
int[] c = {4, 8, 5, 6, 0, 8, 11,15};
int zs = 0;
int s1 = suma(a); Console.WriteLine("Сума елементiв масиву А = {0}", s1);
zs = zs + s1;
int s2 = suma(b); Console.WriteLine("Сума елементiв масиву В = {0}", s2);
zs = zs + s2;
int s3 = suma(c); Console.WriteLine("Сума елементiв масиву C = {0}", s3);
zs = zs + s3;
Console.WriteLine("Сума елементiв даних масивiв = {0}", zs);
Console.ReadKey();
} } }
Для самостійної робота.
1. Задано 4 масиви цілих чисел із різною кількістю елементів. Знайти: а) суму елементів кожного з них. б) кількість парних чисел у кожному з них.
2. З клавіатури вводяться цілі числа (чисел - N). В підпрограмі визначається чи число належить проміжку (-10; 10). Якщо так, то виводити число на екран з відповідним повідомленням.
3. Скориставшись підпрограмами, визначити індекс найменшого елементу масиву, найбільшого елементу масиву. Поміняти їх місцями. Вивчести змінений масив.
Приклад 4. Проаналізуйте хід виконання програмного коду та зміну значень до та після звернення до підпрограми
class Program
{
static void showDouble(int val)
{
val *= 2; Console.WriteLine("подвоєне = {0}" , val );
}
static void Main(string[] args)
{
int myNumber = 5;
Console.WriteLine("мiй номер = {0}", myNumber);
showDouble(myNumber);
Console.WriteLine("мiй номер = {0}", myNumber);
Приклад 5
class Program
{
static void showDouble(ref int val)
{
val *= val;
Console.WriteLine("квадрат номера = {0}", val);
}
static void Main()
{
int myNumber = 5; Console.WriteLine("мiй номер = {0}", myNumber);
showDouble(ref myNumber); Console.WriteLine("мiй новий номер = {0}", myNumber);
} }
Приклад 6
Пошук номера максимального елемента масиву з використанням підпрограм.
class Program
{
// підпрограма пошуку суми елементів масиву
static int maxValue(int[] intArray, out int maxlndex)
{
int maxVal = intArray[0]; maxlndex = 0;
for (int i = 1; i < intArray.Length; i++)
{
if (intArray[i] > maxVal)
{
maxVal = intArray[i]; maxlndex = i;
}
}
return maxVal;
}
static void Main()
{
int[] myArray = { 1, 8, 3, 6, 2, 5, 9, 3, 0, 2 };
int maxlndex; Console.WriteLine("В даному масивi: ");
for (int i = 0; i < 10; i++) Console.Write(myArray[i] + " ");
maxValue(myArray, out maxlndex); Console.WriteLine();
Console.WriteLine("Максимальний eлемент масиву {0}", myArray[maxlndex]);
Console.WriteLine("Його iндекс {0}", maxlndex + 1);
Console.ReadKey();
} }
Приклад 7
Проаналізуйте програмний код та зробіть висновки: як використовуються підпрограми для розв'язування типових задач для довільно заданих масивів.
class Program
{
static int maxValue(int[] intArray, out int maxlndex)
{
int maxVal = intArray[0]; maxlndex = 0; for (int i = 1; i < intArray.Length; i++)
{
if (intArray[i] > maxVal)
maxVal = intArray[i]; maxlndex = i;
}
return maxVal;
}
static void Main()
{
int[] myArray = { 1, 8, 3, 6, 2, 5, 9, 3, 0, 2 }; int[] Array1 = { 0, 5, 3, 12, 2, 7, 9, 3, 9, -4 };
int maxlndex; Console.WriteLine("В даному масивi A: ");
for (int i = 0; i < 10; i++) Console.Write(myArray[i] + " ");
maxValue(myArray, out maxlndex); Console.WriteLine();
Console.WriteLine("Максимальний eлемент масиву {0}", myArray[maxlndex]);
Console.WriteLine("Його iндекс {0}", maxlndex + 1); Console.WriteLine();
Console.WriteLine("В даному масивi B : "); for (int i = 0; i < 10; i++) Console.Write(Array1[i] + " ");
maxValue(Array1, out maxlndex); Console.WriteLine();
Console.WriteLine("Максимальний eлемент масиву {0}", Array1[maxlndex]);
Console.WriteLine("Його iндекс {0}", maxlndex + 1);
Console.ReadKey();
} }
Приклад 8. Обчислення факторіала числа n
class Program
{
static long F(int n)
{
if (n==0 || n==1) return 1; else return n*F(n-1);
}
static void Main()
{
Console.Write("Введи довiльне невiдємне цiле число n=");
int n =int.Parse( Console.ReadLine());
long f = F(n);
Console.WriteLine("{0}!={1}",n, f);
Console.ReadKey();
} }
Завдання для закріплення вивченого матеріалу.
1. Використати рекурсивний алгоритм обчислення факторіала певного числа для обчислення значення виразу: 2!+4!+6!+8!+10!.
2. Опрацювати приклад 11 на власних масивах
3. Обчислити периметр існуючого трикутника (без дослідження умов існування трикутника з даними вимірами), заданого координатами його вершин. Для знаходження довжини відповідної сторони скористайтеся підпрограмою.
Приклад 9. Пошук найменшого спільного кратного
class Program
{
static int NCD(int x, int y)
{
if (x != 0) return NCD((y % x), x); else return y;
}
static int NCK(int x, int y)
{
return (x / NCD(x, y)) * y;
}
static void Main(string[] args)
{
int a, b; Console.WriteLine("Знайдемо найменше спiльне кратне для двох натуральних чисел");
Console.WriteLine("Введiть числа a i b:");
a = Int32.Parse(Console.ReadLine()); b = Int32.Parse(Console.ReadLine());
Console.WriteLine("НСК чисел {0} i {1} дорiвнює {2} ", a, b, NCK(a, b));
Console.Write("Вiдповiдь: ");
Console.WriteLine("НСК ({0};{1}) = {2}", a, b, NCK(a, b));
Console.ReadKey();
}
}
Приклад 10. Пошук найбільшого спільного дільника
class Program
{
private static int NСD(int a, int b)
{
while (a != b) if (a > b) a -= b; else b -= a; return a;
}
static void Main(string[] args)
{
int a, b, c, d; Console.WriteLine("Знайдемо НСД 4 чисел");
Console.WriteLine("Введiть a, b, c ,d:");
a = int.Parse(Console.ReadLine()); b = int.Parse(Console.ReadLine());
c = int.Parse(Console.ReadLine()); d = int.Parse(Console.ReadLine());
Console.WriteLine(string.Format(" НСД = {0}", NCD(NCD(a, b), NCD(c, d))));
Console.ReadKey();
} }
Приклад 11
Написати програму, яка обчислює середнє арифметичне елементів одномірного масиву наперед не відомого типу, використавши підпрограми
class Program
{
public static void Seredne(int[] mas)
{
double s = 0, sr = 0;
for (int i = 0; i < mas.Length; i++)
{
s += mas[i];
}
sr = s / mas.Length;
Console.WriteLine();
Console.WriteLine(" Середнє арифметичне масиву = " + sr);
}
public static void Seredne(float[] mas)
{
Console.WriteLine();
float s = 0, sr = 0;
for (int i = 0; i < mas.Length; i++)
{
s += mas[i];
}
sr = s / mas.Length;
Console.WriteLine("Середнє арифметичне масиву = " + sr);
}
static void Main(string[] args)
{
Random rnd = new Random();
Console.Write("Виберiть тип масиву(1 - int; 2 - float): ");
string s = Console.ReadLine(); switch (s)
{
case "1":
Console.WriteLine("Вибраний тип масиву int!");
int[] mas = new int[10];
for (int i = 0; i < 10; i++)
{
mas[i] = rnd.Next(1, 10);
Console.Write(mas[i] + " ");
}
Seredne(mas);
break;
case "2":
Console.WriteLine("Вибраний тип масиву float!");
float[] mas1 = new float[10];
for (int i = 0; i < 10; i++)
{
mas1[i] = rnd.Next(1, 10); Console.Write(mas1[i] + " ");
}
Seredne(mas1);
break;
}
Console.ReadKey();
} }
Приклад 12
class Program
{
static void Main(string[] args)
{
double k = 0.5; // тут задаємо крок зміни змінної, у вигляді k - крок ітеррації
double m = -1; // тут задаємо нижню межу значення змінної
double n = 4; // тут задаємо верхню межу значення змінної
double f = 0; // Ініціалізуємо значення функції . Наприклад, задана функція виду f(x) = (x^2 + 4) / sin (x) в межах від -1 до 4 знайти її значення з кроком х рівним 0.5
{
for (double i = m; i <= n; i += k)
{
f = 0; f = (Math.Pow(i, 2) + 4) / Math.Sin(i); // Сюда записуємо функцію
// Тепер записуємо недопустимі вирази, як ділення на нуль - їх може бути кілька; тоді їх слід обєднати знаком логічного «АБО», тобто "||”
if (Math.Sin(i) == 0)
{
continue;
}
Console.Title = "Обчислення значення функцii на промiжку"; // вводимо заголовок вікна
// При необхідності виводимо значення змінної, якщо це за умовою не потрібно, то наступний рядок не пишемо
Console.WriteLine("x= {0:F1}", i);
// для х досить 1 знак після коми - це залежить від значення кроку 0,5
// А це значення функції. Цей рядок пишемо обов’язково
Console.WriteLine("f(x)= {0:F13}", f);
Console.WriteLine(); } } } } }
Приклад 13
Дано чотири точки: (a1,a2),(b1,b2),(c1,c2),(d1,d2). Знайти відстані між точками, використавши підпрограму
class Program
{
static void f(double x1, double x2, double y1, double y2, int i)
{
double n; Console.Write("{0}. d= ", i);
n = Math.Sqrt(Math.Pow((x2 - x1), 2) + Math.Pow((y2 - y1), 2));
Console.WriteLine("{0:F4}",n);
}
static void Main(string[] args)
{
Console.Title = "Обчислення вiдстанi мiж точками"; Console.WriteLine("задаємо координати 1 точки");
double a1,a2; a1 = int.Parse(Console.ReadLine()); a2 = int.Parse(Console.ReadLine());
Console.WriteLine("задаємо координати 2 точки");
double b1, b2; b1 = int.Parse(Console.ReadLine()); b2 = int.Parse(Console.ReadLine());
Console.WriteLine("задаємо координати 3 точки");
double c1, c2; c1 = int.Parse(Console.ReadLine()); c2 = int.Parse(Console.ReadLine());
Console.WriteLine("задаємо координати 4 точки");
double d1, d2; d1 = int.Parse(Console.ReadLine()); d2 = int.Parse(Console.ReadLine());
// Шукаємо відстані між точками
f(a1, a2, b1, b2, 0); f(b1, b2, c1, c2, 1); f(c1, c2, d1, d2, 2); f(a1, a2, c1, c2, 3);
f(a1, a2, d1, d2, 4); f(b1, b2, d1, d2, 5); Console.WriteLine();
} }
Приклад 14
class Program
{
static void f(double x1, double x2, double y1, double y2, int i)
{
double n; Console.Write("{0}. d= ", i);
n = Math.Sqrt(Math.Pow((x2 - x1), 2) + Math.Pow((y2 - y1), 2));
Console.WriteLine("{0:F4}",n);
}
static void inputxy(int i, ref double x, double y)
{
Console.WriteLine("задаємо координати {0} точки",i);
x = int.Parse(Console.ReadLine()); y = int.Parse(Console.ReadLine());
}
static void Main(string[] args)
{
Console.Title = "Обчислення вiдстанi мiж точками";
double a1=0;double a2=0; double b1=0; double b2=0;
double c1 = 0; double c2=0; double d1=0; double d2=0;
// Перехід на процедуру вводу координат 4 точок
inputxy(1,ref a1,a2); inputxy(2, ref b1, b2); inputxy(3, ref c1, c2); inputxy(4, ref d1, d2);
// Перехід на процедуру пошуку відстані між точками
Console.WriteLine("Вiдстанi мiж точками");
f(a1, a2, b1, b2, 1); f(b1, b2, c1, c2, 2); f(c1, c2, d1, d2, 3); f(a1, a2, c1, c2, 4);
f(a1, a2, d1, d2, 5); f(b1, b2, d1, d2, 6); Console.WriteLine();
} } }
Приклад 15
Поставлена задача визначення сумарного периметра кількох полів прямокутної форми.
class Program
{
static int Perumetr(int a,int b)
{
int P=0; P=2*(a+b); return P;
}
static void Main(string[] args)
{
Console.WriteLine("Ввести кількість полів прямокутної форми");
int n =int.Parse( Console.ReadLine());
int sp = 0;
for (int i = 1; i <= n; i++)
{
Console.WriteLine("Ввести розміри {0} поля", i);
int a = int.Parse(Console.ReadLine());
int b = int.Parse(Console.ReadLine());
int p1 = Perumetr(a, b);
sp = sp + p1;
}
Console.WriteLine("Сумаоний периметр полів = {0}", sp);
} }
Типова вправа про обчислення сумарної площі кількох ділянок прямокутної форми
class Program
{
// підпрограма вводу даних i визначення площі прямокутного поля
static int Input_ab()
{
Console.Write("Чому дорiвнює довжина поля? ");
int a=int.Parse(Console.ReadLine());
Console.Write("Чому дорiвнює ширина поля? ");
int b=int.Parse(Console.ReadLine());
return a*b;
}
// основна програма (Визначаємо суму площ 3 полів)
static void Main(string[] args)
{
int sp=0;
for (int i = 0; i < 3; i++)
{
int s1 = Input_ab();//звернення до підпрограми
sp += s1;
Console.WriteLine("Площа поля {0}", s1);
}
Console.WriteLine("Cумa площ 3 полів = {0}", sp);
Console.ReadKey();
}
Завдання для самостійного опрацювання
Сільськогосподарський колектив вирощує пшеницю на трьох полях різної форми (прямокутної, квадратної та форми паралелограма). Задайте розміри відповідних полів та врожай зернових з кожного поля та визначте врожайність (кількість тон з га).