NZD i NZS
Učitati dva prirodna broja i ispisati njihov najveći zajednički delilac i najmanji zajednički sadržalac. Napisati metodu static long Nzd(long a, long b).
Primer 1
Ulaz
12 18Izlaz
NZD = 6
NZS = 36Primer 2
Ulaz
7 5Izlaz
NZD = 1
NZS = 35Metoda je imenovani deo programa koji obavlja jedan zadatak. Metode skraćuju program, sprečavaju ponavljanje koda i olakšavaju traženje grešaka. Ovde su statičke metode, koje se pozivaju bez objekta; metode objekata dolaze u lekciji o klasama.
Metoda ima zaglavlje (modifikatori, tip povratne vrednosti, ime, parametri) i telo u vitičastim zagradama. Naredba return vraća rezultat i završava metodu. Imena metoda se pišu velikim početnim slovom.
using System;
class Program
{
// static: metoda pripada klasi, poziva se bez objekta
// int: tip povratne vrednosti; (int x): parametar
static int Kvadrat(int x)
{
return x * x;
}
// void: metoda ništa ne vraća, samo nešto uradi
static void Linija(int duzina, char znak)
{
Console.WriteLine(new string(znak, duzina));
}
static void Main()
{
Linija(20, '=');
for (int i = 1; i <= 4; i++)
Console.WriteLine($"{i} na kvadrat je {Kvadrat(i)}");
Linija(20, '-');
Console.WriteLine($"3^2 + 4^2 = {Kvadrat(3) + Kvadrat(4)}");
}
}
Pri pozivu se argumenti (stvarne vrednosti) dodeljuju parametrima redom: u pozivu Linija(20, '=') parametar duzina dobija 20, a znak dobija '='.
using System;
class Program
{
static bool JeProst(int n)
{
if (n < 2) return false;
for (int d = 2; d * d <= n; d++)
if (n % d == 0) return false; // return odmah završava metodu
return true;
}
static int ZbirCifara(int n)
{
int z = 0;
while (n > 0)
{
z += n % 10;
n /= 10;
}
return z;
}
static int Veci(int a, int b) => a > b ? a : b; // metoda u jednom redu (=>)
static void Main()
{
string[] d = Console.ReadLine().Split(' ');
int a = int.Parse(d[0]), b = int.Parse(d[1]);
// prosti brojevi iz intervala čiji je zbir cifara takođe prost
for (int x = a; x <= b; x++)
if (JeProst(x) && JeProst(ZbirCifara(x)))
Console.Write(x + " ");
Console.WriteLine();
Console.WriteLine($"Veci od {a} i {b} je {Veci(a, b)}");
}
}
Metoda koja vraća bool čini uslov čitljivim: if (JeProst(n)) se čita kao rečenica. Kratka metoda se može napisati u jednom redu, posle oznake =>.
Podrazumevano metoda dobija kopiju vrednosti argumenta, pa promena parametra ne utiče na promenljivu iz poziva. Sa ref metoda radi sa samom promenljivom, a out služi da metoda vrati više rezultata. Reč ref ili out piše se i u pozivu.
using System;
class Program
{
static void Uvecaj(int x)
{
x += 10; // menja se samo kopija
}
static void UvecajRef(ref int x)
{
x += 10; // menja se promenljiva iz poziva
}
static void MinMax(int[] niz, out int min, out int max)
{
min = max = niz[0]; // out parametri moraju dobiti vrednost
foreach (int v in niz)
{
if (v < min) min = v;
if (v > max) max = v;
}
}
static void Main()
{
int a = 5;
Uvecaj(a);
Console.WriteLine($"Posle Uvecaj: {a}");
UvecajRef(ref a);
Console.WriteLine($"Posle UvecajRef: {a}");
MinMax(new[] { 7, -3, 12, 0 }, out int mn, out int mx);
Console.WriteLine($"min = {mn}, max = {mx}");
}
}
Sada je jasno kako radi int.TryParse(tekst, out int broj): metoda vraća bool, a broj upisuje kroz out parametar. Kod nizova i objekata metoda dobija kopiju reference, pa promene elemenata niza ostaju vidljive i bez ref.
using System;
class Program
{
// preklapanje: isto ime, različiti parametri
static double Povrsina(double a) => a * a; // kvadrat
static double Povrsina(double a, double b) => a * b; // pravougaonik
// podrazumevana vrednost parametra
static string Pozdrav(string ime, string jezik = "sr") =>
jezik == "en" ? $"Hello, {ime}!" : $"Zdravo, {ime}!";
// params: proizvoljan broj argumenata
static int Zbir(params int[] brojevi)
{
int z = 0;
foreach (int b in brojevi) z += b;
return z;
}
static void Main()
{
Console.WriteLine(Povrsina(4));
Console.WriteLine(Povrsina(4, 2.5));
Console.WriteLine(Pozdrav("Ana"));
Console.WriteLine(Pozdrav("Ana", "en"));
Console.WriteLine(Pozdrav(jezik: "en", ime: "Marko")); // imenovani argumenti
Console.WriteLine(Zbir(1, 2, 3));
Console.WriteLine(Zbir(10, 20, 30, 40));
Console.WriteLine(Zbir());
}
}
Kompajler bira metodu po broju i tipu argumenata. Dve metode ne mogu se razlikovati samo po tipu povratne vrednosti.
Rekurzivna metoda rešava zadatak tako što poziva sebe za manji problem. Mora imati izlazni slučaj koji se rešava bez novog poziva – inače se program ruši greškom StackOverflowException.
using System;
class Program
{
static long Faktorijel(int n) => n <= 1 ? 1 : n * Faktorijel(n - 1);
static int Nzd(int a, int b) => b == 0 ? a : Nzd(b, a % b); // Euklidov algoritam
static string Binarno(int n) => n < 2 ? n.ToString() : Binarno(n / 2) + (n % 2);
static void Main()
{
Console.WriteLine($"10! = {Faktorijel(10)}");
Console.WriteLine($"NZD(84, 36) = {Nzd(84, 36)}");
Console.WriteLine($"37 binarno = {Binarno(37)}");
}
}
Više o rekurziji i o tome kada je bolja petlja: Rekurzija.
Za svaki zadatak postoji primer, uputstvo i rešenje. Rešenja su provereno tačna na primerima iz teksta.
Učitati dva prirodna broja i ispisati njihov najveći zajednički delilac i najmanji zajednički sadržalac. Napisati metodu static long Nzd(long a, long b).
12 18NZD = 6
NZS = 367 5NZD = 1
NZS = 35Digitalni koren broja dobija se tako što se sabiraju njegove cifre, pa cifre zbira, sve dok ne ostane jednocifren broj (98765 → 35 → 8). Napisati rekurzivne metode ZbirCifara i DigitalniKoren i ispisati digitalni koren učitanog broja (broj staje u long).
9876584931932Main.void mora vratiti vrednost u svakom slučaju – inače greška „not all code paths return a value“.ref i out pišu se i u zaglavlju metode i u pozivu.1. Šta znači void u zaglavlju metode?
2. Metoda promeni vrednost parametra tipa int (bez ref). Šta se dešava sa promenljivom iz poziva?
3. Čemu služi out parametar?
4. Šta svaka rekurzivna metoda mora da ima?