Zbir ispravnih brojeva
U redu su reči razdvojene razmakom. Sabrati sve reči koje su celi brojevi i prebrojati one koje nisu.
Primer
Ulaz
5 abc 12 7.5 -3 xIzlaz
Zbir: 14
Neispravnih: 3Izuzetak (exception) je greška koja nastaje dok program radi: korisnik unese slova umesto broja, deli se nulom, traži se element van niza… Bez obrade, izuzetak prekida program. Blokovi try i catch omogućavaju da program grešku „uhvati“, obradi i nastavi rad.
using System;
class Program
{
static void Main()
{
Console.Write("Unesi broj: ");
try
{
int x = int.Parse(Console.ReadLine()); // može baciti FormatException
Console.WriteLine($"100 / {x} = {100 / x}"); // može baciti DivideByZeroException
}
catch (FormatException)
{
Console.WriteLine("Greska: to nije ceo broj.");
}
catch (DivideByZeroException)
{
Console.WriteLine("Greska: deljenje nulom.");
}
Console.WriteLine("Program nastavlja rad.");
}
}
Kada u bloku try nastane izuzetak, ostatak bloka se preskače i traži se prvi catch čiji tip odgovara. Posle obrade program nastavlja iza celog try-catch. Najčešći izuzeci su prikazani u tabeli:
| Izuzetak | Kada nastaje |
|---|---|
FormatException | tekst nije u očekivanom obliku (int.Parse("abc")) |
DivideByZeroException | celobrojno deljenje nulom |
IndexOutOfRangeException | indeks van granica niza |
ArgumentOutOfRangeException | indeks van granica liste ili stringa |
NullReferenceException | korišćenje promenljive čija je vrednost null |
KeyNotFoundException | čitanje ključa koji ne postoji u rečniku |
OverflowException | broj ne staje u tip (npr. int.Parse("99999999999")) |
Blok finally izvršava se uvek – i kada izuzetka nema i kada je uhvaćen. Koristi se za „pospremanje“: zatvaranje fajla, veze sa bazom… Iza tipa u catch može se navesti ime promenljive, pa se dobija objekat izuzetka sa podacima o grešci.
using System;
class Program
{
static void Main()
{
int[] niz = { 10, 20, 30 };
for (int i = 2; i <= 3; i++)
{
try
{
Console.WriteLine($"niz[{i}] = {niz[i]}");
}
catch (IndexOutOfRangeException e)
{
Console.WriteLine($"Uhvacen izuzetak: {e.GetType().Name}");
}
finally
{
Console.WriteLine($"finally za i = {i}");
}
}
}
}
Svojstvo e.Message sadrži opis greške (na jeziku operativnog sistema), a catch (Exception e) hvata izuzetak bilo kog tipa – zato se piše poslednji, posle konkretnijih.
Hvatanje izuzetaka je sporije i nepreglednije od obične provere. Kada se greška može predvideti – kao pogrešan unos – bolje je proveriti unapred, npr. metodom TryParse. Izuzeci su za situacije koje se ne mogu lako proveriti.
using System;
class Program
{
// ponavlja unos dok korisnik ne unese ceo broj iz opsega [min, max]
static int UcitajBroj(string poruka, int min, int max)
{
while (true)
{
Console.Write(poruka);
if (int.TryParse(Console.ReadLine(), out int x) && x >= min && x <= max)
return x;
Console.WriteLine($"Unesi ceo broj od {min} do {max}.");
}
}
static void Main()
{
int ocena = UcitajBroj("Ocena: ", 1, 5);
Console.WriteLine($"Uneta ocena: {ocena}");
}
}
I naš kod može da baci izuzetak naredbom throw, kada metoda dobije podatke sa kojima ne može da radi. Tako metoda ne mora sama da ispisuje poruke – greška se prijavljuje onome ko je metodu pozvao.
using System;
class Racun
{
public decimal Stanje { get; private set; }
public void Uplati(decimal iznos) => Stanje += iznos;
public void Isplati(decimal iznos)
{
if (iznos <= 0)
throw new ArgumentException("Iznos mora biti pozitivan.");
if (iznos > Stanje)
throw new InvalidOperationException($"Nema dovoljno novca (stanje: {Stanje}).");
Stanje -= iznos;
}
}
class Program
{
static void Main()
{
var r = new Racun();
r.Uplati(500);
decimal[] zahtevi = { 200, -50, 1000, 300 };
foreach (decimal z in zahtevi)
{
try
{
r.Isplati(z);
Console.WriteLine($"Isplaceno {z}, stanje {r.Stanje}");
}
catch (ArgumentException e)
{
Console.WriteLine("Odbijeno: " + e.Message);
}
catch (InvalidOperationException e)
{
Console.WriteLine("Odbijeno: " + e.Message);
}
}
}
}
Sopstveni izuzetak je klasa koja nasleđuje klasu Exception. Ime joj se po dogovoru završava sa Exception, a poruka se prosleđuje konstruktoru bazne klase sa : base(poruka). Isti postupak koristi i napredni primer sa putnicima u vozu.
using System;
using System.Collections.Generic;
class PrekoracenKapacitetException : Exception
{
public int Kapacitet { get; }
public PrekoracenKapacitetException(int kapacitet)
: base($"Prekoracen kapacitet od {kapacitet} mesta.")
{
Kapacitet = kapacitet;
}
}
class Autobus
{
private readonly List<string> putnici = new List<string>();
private readonly int kapacitet;
public Autobus(int kapacitet) { this.kapacitet = kapacitet; }
public int Broj => putnici.Count;
public void Udji(string ime)
{
if (putnici.Count == kapacitet)
throw new PrekoracenKapacitetException(kapacitet);
putnici.Add(ime);
}
}
class Program
{
static void Main()
{
var bus = new Autobus(3);
string[] red = { "Ana", "Bojan", "Ceca", "Dule", "Ema" };
try
{
foreach (string ime in red)
{
bus.Udji(ime);
Console.WriteLine($"{ime} je usao/la.");
}
}
catch (PrekoracenKapacitetException e)
{
Console.WriteLine(e.Message);
}
finally
{
Console.WriteLine($"U autobusu: {bus.Broj}");
}
}
}
Za svaki zadatak postoji primer, uputstvo i rešenje. Rešenja su provereno tačna na primerima iz teksta.
U redu su reči razdvojene razmakom. Sabrati sve reči koje su celi brojevi i prebrojati one koje nisu.
5 abc 12 7.5 -3 xZbir: 14
Neispravnih: 3Svaki red ulaza je oblika a op b (celi brojevi i operacija + - * /), a ulaz se završava redom kraj. Za svaki red ispisati rezultat (deljenje je celobrojno) ili poruku Greska: neispravan broj, Greska: deljenje nulom ili Greska: nepoznata operacija X. Greške obraditi izuzecima.
8 + 5
7 / 0
9 ^ 2
12 * x
20 / 6
kraj13
Greska: deljenje nulom
Greska: nepoznata operacija ^
Greska: neispravan broj
3catch { } sakriva greške.catch blokovi idu pre opštijih (catch (Exception) je poslednji).TryParse je bolji od hvatanja FormatException.Exception, a klasa nasleđuje Exception.1. Koji izuzetak baca int.Parse("abc")?
2. Kada se izvršava blok finally?
3. Kojom naredbom metoda sama prijavljuje grešku?
4. Koju klasu nasleđuje sopstveni izuzetak?