Programiranje 3 - Razred denarnica

Programiranje 3 - Razred denarnica

Avtor: Petra Adamič

Opis problema

Sestavi razred Denarnica, ki vsebuje tri komponente:

  • celoštevilsko spremenljivko, ki predstavlja količino evrov v njej
  • celoštevilsko spremenljivko, ki predstavlja količino centov v njej
  • spremenljivko tipa string, ki vsebuje ime lastnika denarnice.
  • Napiši metode get in set.
  • Napiši metodo Opis(), ki vrne niz V denarnici, katere lastnik je #ime_lastnika, je #st_evrov evrov in #st_centov centov.
  • Izračunaj, koliko denarja imajo skupaj osebe v tabeli Denarnica[].
  • Cela skupina (beri vsi v tabeli) lastnikov denarnic se je odpravila v banko. Tam so vse svoje cente "pretopili" v evre (kolikor je šlo, seveda). Če je nekdo imel prej 6€ in 245 centov, ima sedaj v denarnici 8€ in 45 centov.
  • Izpiši imena vseh tistih oseb, ki si lahko privoščijo nakup banjice sladoleda, ki stane 4€ 45 centov. Seveda so vse osebe, ki to lahko, opravile nakup. Pazi, da bodo njihove denarnice odražale to stanje.
  • Iz dane datoteke denarnic izbriši vse, v katerih je vsaj X in ne več kot Y denarja.
  • Nekatere osebe imajo več denarnic. Tvori novo datoteko s podatki o denarnicah tako, da se v njej vseka oseba pojavi le enkrat. Praznih denarnic ne beleži.

Kaj naj vsebuje razred

  • Minimalni (tj. prazni) kontruktor public Razred(), ki tvori objekt s privzetimi (smiselnimi!) vrednostmi.
  • Metodo public override string ToString(), ki vse podatke v objektu zapiše v obliki niza. Podatki naj bodo med seboj ločeni z znakom ';'.
  • Polni konstruktor public Razred(string s), ki s klicem Razred(niz) generira tak objekt Razred r, za katerega velja niz = r.ToString().
  • Metodo DodajNaDatoteko(string imeDatoteke), ki objekt this zapiše (oz. doda; glej metodo File.AppendText()) kot vrstico this.ToString() v tekstovni datoteki.
  • Metodo PreberiZDatoteke(string imeDatoteke), ki vrne tabelo objektov, kjer posamezni objekt vsebuje podatke, ki so zapisani v posamezni vrstici tekstovne datoteke.
  • Metodo IzpisiDatoteko(string imeDatoteke), ki izpiše vsebino datoteke.
  • Metodo TvoriDatoteke(string imeDatoteke, int stElementov), ki tvori naključno datoteko.
  • Če je potrebno, napišite še metodo, ki izpiše tabelo elementov tega razreda. Vsi razredi morajo biti robustni – vsi konstruktorji in metode morajo biti taki, da objekta ne spravijo v nesmiselno stanje. Če je potrebno, pri klicu metode s nedopustnimi parametri sproži izjemo. Razred je potrebno napisati kot 'class library' v ločenem projektu v isti rešitvi. Pri sestavljanju razredov si prej oglejte probleme, ki jih rešujete, da boste vedeli, kako mora biti razred zgrajen (katere podatke in metode naj vsebuje). V testnem programu, s katerim prikažete ključne funkcionalnosti razreda, naredite naslednje:
  • Napišite ustrezne metode za reševanje zastavljenih problemov.
  • V programu samem pa po vrsti
  • Pokličite metodo, ki na datoteko zapiše ducat objektov.
  • Preberite vse podatke z datoteke v tabelo.
  • Tabelo pregledno izpišite.
  • Nato kličite metode, ki so potrebne, da rešite zastavljene probleme in pregledno izpišite rezultate.
  • Na koncu na isto datoteko ponovno zapišite vseh objektov (ne glede na to, ali so jih zgornje metode spremenile ali ne).

Ideja rešitve

Ideja je, da za dani problem najprej ustvarimo razred denarnica, s pomočjo katerega v testnem programu ustvarimo objekte denarnica. S pomočjo objektov in pomožnih metod lahko rešimo zastavljene probleme.

Koda razreda

public class Denarnica
    {
        #region Spremenljivke

        /// <summary>
        /// privatna spremenljivka za število evrov
        /// </summary>
        private int _StEvrov;

        /// <summary>
        /// javna spremenljivka za število evrov
        /// </summary>
        public int StEvrov
        {
            get { return this._StEvrov; }
            set
            {
                if (value < 0)
                    throw new ArgumentException("V denarnici ne more biti negativno število evrov.");
                else
                    this._StEvrov = value;
            }
        }

        /// <summary>
        /// privatna spremenljivka za število centov
        /// </summary>
        private int _StCentov;

        /// <summary>
        /// javna spremenljivka za število centov
        /// </summary>
        public int StCentov
        {
            get { return this._StCentov; }
            set
            {
                if (value < 0)
                    throw new ArgumentException("V denarnici ne more biti negativno število centov.");
                else
                    this._StCentov = value;
            }
        }

        /// <summary>
        /// privatna spremenljivka za ime lastnika
        /// </summary>
        private string _ImeLastnika;

        /// <summary>
        /// javna spremenljivka za ime lastnika
        /// </summary>
        public string ImeLastnika
        {
            get { return this._ImeLastnika; }
            set { this._ImeLastnika = value; }
        }

        #endregion

        //naključni generator
        public static Random generator = new Random();

        #region Konstruktorji

        /// <summary>
        /// minimalni konstruktor
        /// </summary>
        public Denarnica()
        {
            this.ImeLastnika = "Brez lastnika";
            this.StEvrov = 0;
            this.StCentov = 0;
        }


        /// <summary>
        /// konstruktor nad nizom tipa niz=r.ToString()
        /// </summary>
        /// <param name="s"></param>
        public Denarnica(string s)
        {
            string[] sez = s.Split(';');
            this.ImeLastnika = sez[0];
            this.StEvrov = int.Parse(sez[1]);
            this.StCentov = int.Parse(sez[2]);
        }
        #endregion

        /// <summary>
        /// podatke zapišemo v obliki niza
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return _ImeLastnika + ";" + _StEvrov + ";" + _StCentov;
        }


        /// <summary>
        /// vrne opis denarnice
        /// </summary>
        /// <returns></returns>
        public string Opis()
        {
            return "V denarnici, katere lastnik je " + ImeLastnika + ", je " + StEvrov + " evrov in " + StCentov + " centov.";
        }


        /// <summary>
        /// metoda zasluži
        /// </summary>
        /// <param name="eur"></param>
        /// <param name="cent"></param>
        public void Zasluzi(int eur, int cent)
        {
            int vsota1 = (this.StEvrov) * 100 + this._StCentov;
            int vsota2 = (eur) * 100 + cent;

            int vsota = vsota1 + vsota2;

            this.StCentov = vsota % 100;
            this.StEvrov = vsota / 100;
        }


        /// <summary>
        /// metoda plačaj
        /// </summary>
        /// <param name="eur"></param>
        /// <param name="cent"></param>
        public void Placaj(int eur, int cent)
        {
            int vsota1 = (this.StEvrov) * 100 + this._StCentov;
            int vsota2 = (eur) * 100 + cent;

            int vsota = vsota1 - vsota2;

            this.StCentov = vsota % 100;
            this.StEvrov = vsota / 100;
        }


        #region Datoteke

        /// <summary>
        /// na datoteko zapiše objekt this kot vrstico this.Tostring()
        /// </summary>
        /// <param name="imeDatoteke"></param>
        public void DodajNaDatoteko(string imeDatoteke)
        {
            StreamWriter pisi;
            if (!File.Exists(imeDatoteke))
            {
                pisi = File.CreateText(imeDatoteke);
            }
            else
            {
                pisi = File.AppendText(imeDatoteke);
            }
            pisi.WriteLine(this.ToString());
            pisi.Close();
        }


        /// <summary>
        /// vrne tabelo objektov, kjer posamezni objekt vsebuje podatke,
        /// ki so zapisani v posamezni vrstici datoteke
        /// </summary>
        /// <param name="imeDatoteke"></param>
        /// <returns></returns>
        public static List<Denarnica> PreberiZdatoteke(string imeDatoteke)
        {
            List<Denarnica> sez = new List<Denarnica>();
            if (!File.Exists(imeDatoteke))
                throw new FileNotFoundException("Datoteka ne obstaja");

            string vrstica = "";
            StreamReader beri = new StreamReader(imeDatoteke);

            while ((vrstica = beri.ReadLine()) != null)
            {
                sez.Add(new Denarnica(vrstica));
            }
            beri.Close();
            return sez;
        }


        /// <summary>
        /// izpiše vsebino datoteke
        /// </summary>
        /// <param name="imeDatoteke"></param>
        public static void IzpisiDatoteko(string imeDatoteke)
        {
            if (!File.Exists(imeDatoteke))
                throw new FileNotFoundException("Datoteka ne obstaja");
            string vrstica = "";
            using (StreamReader beri = new StreamReader(imeDatoteke))
            {
                while ((vrstica = beri.ReadLine()) != null)
                {
                    Console.WriteLine(vrstica);
                }
            }
        }

        /// <summary>
        /// tvori naključno datoteko
        /// </summary>
        /// <param name="imeDatoteke"></param>
        /// <param name="stElementov"></param>
        public void TvoriDatoteko(string imeDatoteke, int stElementov)
        {
            for (int i = 0; i < stElementov; i++)
            {
                string ime = NakljucniNiz(generator.Next(15));
                int stEuro = generator.Next();
                int stCent = generator.Next();
                using (StreamWriter pisi = new StreamWriter(imeDatoteke, true))
                {
                    pisi.WriteLine(this.ToString());
                }
            }
        }
        #endregion

        public static string NakljucniNiz(int dolzina = 8)
        /*tvorimo naključni niz dolžine dolzina, ki vsebujejo črke od a do z, angleška abeceda*/
        {
            string niz = "";
            for (int i = 0; i < dolzina; i++)
            {
                niz += (char)('a' + generator.Next(26)); //dobimo znake med a in z, s kodo od a naprej, znak prištevamo nizu
            }
            return niz;
        }
    }

Razlaga razreda

V razredu ustvarimo tri spremenljivke, eno za število evrov, eno za število centov in eno za ime lastnika posamezne denarnice. Pri številčnih spremenljivkah preverimo, če je vnos pozitivno število, v nasprotnem primeru vržemo izjemo.

Nato naredimo dva konstruktorja. Prvi konstruktor je minimalni, kjer imamo v denarnici brez lastnika 0 denarja. Drugi konstruktor za vhodni podatek dobi niz tipa niz = this.ToString() in iz niza dobi podatke o denarnici.

Nato imamo metodo, ki zapiše podatke o denarnici v obliki niza, kjer so posamezni podatki ločeni s podpičjem. Metoda Opis izpiše podatke o denarnici v obliki stavka.

Nato imamo metodi zasluži in plačaj, kjer najprej vse evre pretopimo v cente, nato prištejemo ali odštejemo podano vsoto denarja in na koncu zopet ločimo na evre in cente.

Nato imamo odsek z delom z datotekami. Imamo metodo, ki posamezno denarnico doda na datoteko. Na datoteko se izpiše denarnica izpisana, kot jo vrne metoda ToString. Nato imamo metodo, ki nam podatke o denarnicah iz datoteke shrani v seznam denarnic. Pri branju iz niza pretvorimo v objekt tipa denarnica s pomočjo drugega konstruktorja. Predzadnja metoda izpiše celotno vsebino datoteke po vrsticah. Zadnja metoda pa ustvari datoteko z naključnimi denarnicami. S pomočjo naključnega generatorja dobimo naključna števili in naključni niz.

Koda testnega programa

class Program
    {
        #region Metode
        public static int VsotaDenarja(List<Denarnica> denarnica)
        {
            int vsota = 0;
            int evri = 0;
            int centi = 0;
            foreach (Denarnica d in denarnica)
            {
                evri += d.StEvrov;
                centi += d.StCentov;
            }
            vsota += evri * 100 + centi;
            return vsota;
        }

        public static void PretopiCente(string imeDatoteke)
        {
            List<Denarnica> denarnica = Denarnica.PreberiZdatoteke(imeDatoteke);
            if (File.Exists(imeDatoteke))
            {
                File.Delete(imeDatoteke);
            }
           foreach (Denarnica d in denarnica)
            {
                if (d.StCentov > 99)
                {
                    d.StEvrov += d.StCentov / 100;
                    d.StCentov = d.StCentov % 100;
                    d.DodajNaDatoteko(imeDatoteke);
                }
                else
                    d.DodajNaDatoteko(imeDatoteke);
            }
        }


        public static List<string> Sladoled(string imeDatoteke, int eur, int cent)
        {
            List<string> sez = new List<string>();
            int cena=eur*100 + cent;
            List<Denarnica> denar = Denarnica.PreberiZdatoteke(imeDatoteke);
            PretopiCente(imeDatoteke);
            if (File.Exists(imeDatoteke))
            {
                File.Delete(imeDatoteke);
            }
            foreach (Denarnica d in denar)
            {
                int vsota = d.StEvrov * 100 + d.StCentov;
                if (vsota >= cena)
                {
                    sez.Add(d.ImeLastnika);
                    d.Placaj(eur, cent);
                    d.DodajNaDatoteko(imeDatoteke);
                }
            }
            return sez;
        }


        public static void Izbriši(string imeDatoteke, int x, int y)
            //x in y sta izražena v centih
        {
            List<Denarnica> denar = Denarnica.PreberiZdatoteke(imeDatoteke);
            PretopiCente(imeDatoteke);
            if (File.Exists(imeDatoteke))
            {
                File.Delete(imeDatoteke);
            }
            foreach (Denarnica d in denar)
            {
                int vsota = d.StEvrov * 100 + d.StCentov;
                if (x > vsota || y < vsota)
                {
                    d.DodajNaDatoteko(imeDatoteke);
                }
            }
        }

        public static void EnaDenarnica(string imeDatoteke)
        {
            List<Denarnica> denar = Denarnica.PreberiZdatoteke(imeDatoteke);
            if (File.Exists(imeDatoteke))
            {
                File.Delete(imeDatoteke);
            }

            for (int i = 0; i < denar.Count; i++)
            {
                for (int j=i+1; j<denar.Count; j++)
                {
                    if (denar[i].ImeLastnika == denar[j].ImeLastnika)
                    {
                        denar[i].Zasluzi(denar[j].StEvrov, denar[j].StCentov);
                        denar[j].Placaj(denar[j].StEvrov, denar[j].StCentov);
                    }
                }
                if (denar[i].StEvrov * 100 + denar[i].StCentov > 0)
                {
                    denar[i].DodajNaDatoteko(imeDatoteke);
                }

            }
        }
        #endregion

        static void Main(string[] args)
        {

           string dat = "denarnice.txt";
           //če že ostaja jo izbrišemo
            if (File.Exists(dat))
           {
               File.Delete(dat);
           }

            //na datoteko zapišemo ducat objektov
            string[] imena = { "Petra", "Miran","Eva", "Petra", "Urša","Manca","Željko","Natalija","Gregor","Matija","Erika","Andrej","Lojze","Janja","Marko"};

            Random gen = new Random();//generator nakljucnih stevil
            for (int i = 0; i < imena.Length; i++)//naredimo 12 novih denarnic
            {
                string niz="";
                int evri = gen.Next(1, 100);//nakljucno število med 1 in 100
                int centi = gen.Next(1, 1000);//nakljucno število med 1 in 1000
                string lastnik = imena[i];//ime lastnika denarnice
                niz += lastnik + ";" + evri + ";" + centi;
                Denarnica d = new Denarnica(niz);//nova denarnica
                d.DodajNaDatoteko(dat);//denarnico dodamo na datoteko
            }

            Console.WriteLine("Uporaba metode izpis datoteke:");
            Denarnica.IzpisiDatoteko(dat);
            Console.WriteLine();
            Console.ReadKey();
            Console.WriteLine("Uporaba metode preberi z datoteke in izpis seznama:");

            //preberemo vse podatke iz datoteke v seznam
            List<Denarnica> sez = Denarnica.PreberiZdatoteke(dat);
            //tabelo pregledno izpišemo
            for (int i = 0; i < sez.Count; i++)
            {
                Console.WriteLine(sez[i]);
            }

           // izračunamo, koliko denarja imajo skupaj osebe v seznamu:
            int vsota = VsotaDenarja(sez);
            int c = vsota % 100;
            int e = vsota / 100;
            Console.ReadKey();
            Console.WriteLine("Vsota denarja je " + e + " evrov in " + c + "centov\n");


           // cela skupina pretopi cente v evre:
            Console.ReadKey();
            PretopiCente(dat);
            Console.WriteLine("Pretopi cente:");
            List<Denarnica> sezp = Denarnica.PreberiZdatoteke(dat);
            for (int i = 0; i < sezp.Count; i++)
            {
                Console.WriteLine(sezp[i]);
            }
            Console.ReadKey();
            //imena vseh tistih oseb, ki si lahko privoščijo nakup banjice sladoleda, ki stane 4€ 45 centov.
            Console.WriteLine("\nSladoled si lahko privoščijo:");
            List<string> slad = Sladoled(dat, 4, 45);
            foreach (string ime in slad)
            {
                Console.WriteLine(ime);
            }
            Console.WriteLine("\nKupimo sladoled za 4,45:");
            List<Denarnica> sezs = Denarnica.PreberiZdatoteke(dat);
            for (int i = 0; i < sezs.Count; i++)
            {
                Console.WriteLine(sezs[i]);
            }
            Console.WriteLine();

            Console.ReadKey();
            //izbrišemo vse denarnice, kjer je vsaj x in največ y denarja
            Console.WriteLine("\nIzbrišemo iz datoteke vse denarnice, ki imajo vsaj 3400 in največ 5700 centov: ");
            Izbriši(dat, 3400, 5700);
            Console.WriteLine();
            List<Denarnica> sezn = Denarnica.PreberiZdatoteke(dat);
            for (int i = 0; i < sezn.Count; i++)
            {
                Console.WriteLine(sezn[i]);
            }
            Console.WriteLine();
            Console.ReadKey();
            //združimo denarnice istega lastnika:
            Console.WriteLine("Združimo denarnice istega lastnika:");
            EnaDenarnica(dat);
            List<Denarnica> sez2 = Denarnica.PreberiZdatoteke(dat);
            Console.WriteLine();
            for (int i = 0; i < sez2.Count; i++)
            {
                Console.WriteLine(sez2[i]);
            }
            Console.WriteLine();

            Console.ReadKey();
            Console.WriteLine("Na koncu imamo tako datoteko:");
            //preberemo vse podatke iz datoteke v seznam
            List<Denarnica> sez3 = Denarnica.PreberiZdatoteke(dat);
            if (File.Exists(dat))
            {
                File.Delete(dat);
            }

            //na isto datoteko ponovno zapišemo vse objekte
            foreach (Denarnica d in sez3)
            {
                d.DodajNaDatoteko(dat);
            }

            //tabelo pregledno izpišemo
            for (int i = 0; i < sez3.Count; i++)
            {
                Console.WriteLine(sez3[i]);
            }
            Console.ReadKey();
        }

Razlaga testnega programa

Najprej napišemo pomožne metode, ki bodo rešile naše naloge. Prva metoda izračuna koliko je skupna vsota denarja vseh denarnic na datoteki. Pri tem v bistvu računamo vsoto denarja v seznamu, ki ga dobimo iz datoteke. Nato imamo metodo, ki cente pretopi v evre v primeru, da imamo več kot 99 centov. V tem primeru število centov delimo s 100 in to prištejemo evrom, število centov nam da ostanek pri deljenju s 100. Naslednja metoda preveri, kateri lastniki denarnic imajo dovolj denarja za nakup sladoleda, ki stane 4,45€. Tiste lastnike, ki si nakup lahko privoščijo, shranimo v seznam imen. Metoda izbriši poskrbi, da iz datoteke izbrišemo vse denarnice, kjer je več denarja kot prvi podani podatek in manj kot drugi podani podatek.

Testni primeri

(razred-test.PNG)

Testni primeri

(razred-test2.PNG)

Testni primeri

(razred-test3.PNG)

Filmček

0%
0%