HTML

Programozó Páternoszter

Ez a Programozó Páternoszter (PP) blogja, a programozásról szól. Aktualitása, hogy a Debreceni Egyetem Informatikai Kara Magasszintű programozási nyelvek 1-2, C++ esattanulmányok, Java esettanulmányok című kurzusainak blogja is egyben.

A vadászat

A Debreceni Egyetem Programozói Évkönyve: az UDPROG projekt. A szakmai fórumunk a Facebook-en. Az új előadások a prezin.
A régi előadások:
Prog1:
1. C bevezetés
2. C tárgyalás
3. C befejezés
4. C a gyakorlatban
5. C++ bevezetés
6. C++ tárgyalás
7. C++ befejezés
8. C++ a gyakorlatban
9. Java platform bevezetés
10. Kvantuminformatikai alg. bev.
Prog2:
1. Java bevezetés
2. Java tárgyalás
3. Java befejezés
4. Java a gyakorlatban
5. Software Engineering bev.
6. Java EE bevezetés
7. AspectJ bevezetés
8. BPMN-BPEL SOA programozás
9. C++ haladó
10. Tensorflow

Kövess engem!

Friss topikok

Linkblog

Imádni fogják a C++-t, egy emberként, tiszta szívből (*)

2011.03.31. 14:37 nb

Miután az 5 előadás verem{1-17}.cpp példáit reprodukáltuk, megrágtuk, elfogyasztottuk, majd kimásztunk az asztal alól, ahová unalmunkban közben be-beestünk, kicsit komolyabb fába vágtuk a fejszét: a Tömör a gyönyörben kifejlesztett C struktúrás LZW (bináris) fa építőnket több lépésben átírjuk C++-ba. Jó (K&R) szokás szerint továbbfejlesztések sorát készítjük majd el, e mostanival kezdjük a C++ sorozatot. Mikor vagy kész? Ha az 5. alőadás alapján készített progid lefordul és ugyanazt nyomja ki, mint a Labormérés otthon, avagy hogyan dolgozok fel egy pédát posztbeli teszteléskor a C változat.

Kezdjük! Az első változatot tehát úgy készítjük, hogy nézzük a C kódot és melegében írjuk át C++-ra (ennek megfelelően egyelőre nem használunk például referenciákat) egyszerűen csak egy osztállyal helyettesítjük a fa csomópontjait leíró struktúrát.

Az osztálynév nem a legszerencsésebb, lehetne LZWBinFaCsomopont is, de most a gyökér csomópont kitüntetett abban az értelemben, hogy számunkra ő lesz majd maga a fa, innen a név.

class LZWBinFa
{

    char betu;
    LZWBinFa *balNulla;
    LZWBinFa *jobbEgy;

public:
    LZWBinFa (char b = '/'):betu (b), balNulla (NULL), jobbEgy (NULL) {};
    ~LZWBinFa () {};

 A struktúrával teljesen analóg módon itt is megvan a két önhivatkozó tag, itt hogy '0'-val vagy '1'-el címkézve vettük fel az új (a gyermek) csomópontot, azt egy char-ban (betu) tároljuk (ennek kapcsán megnézheted a 3. hullám kapcsolódó 1 trófeását). Konstruktorunkat tipikusan majd ezzel a '0' vagy '1' címkével fogjuk hívni, de ha ezt nem adjuk meg, akkor a gyökér "jele" a '/' betű lesz feltételezve. Továbbá az újonan készített csomópontok gyerekekre mutató mutatóját úgy állítjuk be, hogy kezdetben nincsenek gyerekei a csomópontnak /balNulla (NULL), jobbEgy (NULL)/ Az alábbi kódcsiperben tehát a "gyoker" az az LZWBinFa csomópont objektum, amiben a "betu" értéke a '/' jel, azt is észrevehetjük, hogy lokális változóként vettük fel, nem kell majd szabadítani. Kezdetben erre a gyökérre állítjuk a "fa" mutatót, s majd ez mutatja mindig, hogy az algoritmus üzeme során hol vagyunk éppen a fában.

 

int
main ()
{
    char b;
    LZWBinFa gyoker, *fa = &gyoker;

    while (std::cin >> b)
    {
        if (b == '0')
        {
            // van '0'-s gyermeke az aktuális csomópontnak?
            if (!fa->nullasGyermek ()) // ha nincs, csinálunk
            {
                LZWBinFa *uj = new LZWBinFa ('0');
                fa->ujNullasGyermek (uj);
                fa = &gyoker;
            }
            else // ha van, arra lépünk
            {
                fa = fa->nullasGyermek ();
            }
        }

 

 A működés teljesen ugyanaz, csak kicsit egyszerűsödött a kód, s jobban is olvasható, mint a C változat. Egyszerűen meghagytuk a C program logikáját és a struktúra használata helyett beütöttük az újdonsült osztályunk használatát. A konstruktor és a new operátor használata is levett pár sort a meglévő kódból a vállunkról. Fordítsuk, futtassuk:

[norbi@sgu ~]$ g++  z.cpp -o z
[norbi@sgu ~]$ ./z <tesztminta.txt
------------1(3)
---------1(2)
------1(1)
---------0(2)
------------0(3)
---------------0(4)
---/(0)
---------1(2)
------0(1)
---------0(2)
OK, ugyanaz.
Tekerj a továbbra a teljes forrásért és persze a folytatásért.

*: "Imádni fogják a légiót, egy emberként, tiszta szívből", www.imdb.com/title/tt0126388/

  

// z.cpp
//
// LZW fa építő C++ átizata a C valtozatbol
// Programozó Páternoszter
//
// Copyright (C) 2011, Bátfai Norbert, nbatfai@inf.unideb.hu, nbatfai@gmail.com
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// Ez a program szabad szoftver; terjeszthetõ illetve módosítható a
// Free Software Foundation által kiadott GNU General Public License
// dokumentumában leírtak; akár a licenc 3-as, akár (tetszõleges) késõbbi
// változata szerint.
//
// Ez a program abban a reményben kerül közreadásra, hogy hasznos lesz,
// de minden egyéb GARANCIA NÉLKÜL, az ELADHATÓSÁGRA vagy VALAMELY CÉLRA
// VALÓ ALKALMAZHATÓSÁGRA való származtatott garanciát is beleértve.
// További részleteket a GNU General Public License tartalmaz.
//
// A felhasználónak a programmal együtt meg kell kapnia a GNU General
// Public License egy példányát; ha mégsem kapta meg, akkor
// tekintse meg a <http://www.gnu.org/licenses/> oldalon.
//
//
// Version history:
//
// 0.0.1, http://progpater.blog.hu/2011/02/19/gyonyor_a_tomor
// 0.0.2, csomópontok mutatóinak NULLázása (nem fejtette meg senki :)
// 0.0.3, http://progpater.blog.hu/2011/03/05/labormeres_otthon_avagy_hogyan_dolgozok_fel_egy_pedat
// 0.0.4, a C verzióból svn: bevezetes/C/ziv/z.c átírjuk C++-ra
//        http://progpater.blog.hu/2011/03/31/imadni_fogjatok_a_c_t_egy_emberkent_tiszta_szivbol
//

#include <iostream>

class LZWBinFa
{
public:
    LZWBinFa (char b = '/'):betu (b), balNulla (NULL), jobbEgy (NULL) {};
    ~LZWBinFa () {};
    LZWBinFa *nullasGyermek () {
        return balNulla;
    }
    LZWBinFa *egyesGyermek ()
    {
        return jobbEgy;
    }
    void ujNullasGyermek (LZWBinFa * gy)
    {
        balNulla = gy;
    }
    void ujEgyesGyermek (LZWBinFa * gy)
    {
        jobbEgy = gy;
    }
    void kiir (void)
    {
        melyseg = 0;
        kiir (this);
    }
    void szabadit (void)
    {
        szabadit (jobbEgy);
        szabadit (balNulla);
    }


private:
    char betu;
    LZWBinFa *balNulla;
    LZWBinFa *jobbEgy;

    LZWBinFa (const LZWBinFa &);
    LZWBinFa & operator=(const LZWBinFa &);

    int melyseg;

    void kiir (LZWBinFa * elem)
    {
        if (elem != NULL)
        {
            ++melyseg;
            kiir (elem->jobbEgy);
            // ez a postorder bejáráshoz képest
            // 1-el nagyobb mélység, ezért -1
            for (int i = 0; i < melyseg; ++i)
                std::cout << "---";
            std::cout << elem->betu << "(" << melyseg - 1 << ")" << std::endl;
            kiir (elem->balNulla);
            --melyseg;
        }
    }
    void szabadit (LZWBinFa * elem)
    {
        if (elem != NULL)
        {
            szabadit (elem->jobbEgy);
            szabadit (elem->balNulla);
            delete elem;
        }
    }

};

int
main ()
{
    char b;
    LZWBinFa gyoker, *fa = &gyoker;
    
    while (std::cin >> b)
    {
        if (b == '0')
        {
            // van '0'-s gyermeke az aktuális csomópontnak?
            if (!fa->nullasGyermek ()) // ha nincs, csinálunk
            {
                LZWBinFa *uj = new LZWBinFa ('0');
                fa->ujNullasGyermek (uj);
                fa = &gyoker;
            }
            else // ha van, arra lépünk
            {
                fa = fa->nullasGyermek ();
            }
        }
        else
        {
            if (!fa->egyesGyermek ())
            {
                LZWBinFa *uj = new LZWBinFa ('1');
                fa->ujEgyesGyermek (uj);
                fa = &gyoker;
            }
            else
            {
                fa = fa->egyesGyermek ();
            }
        }
    }

    gyoker.kiir ();
    gyoker.szabadit ();

    return 0;
}

 Érezni némi zavart az erőben, hiszen a mélység, ami a C-ben globális volt, most minden csomópontnak tagja... Persze ráfoghatnánk, hogy direkt így akartuk és az építés során minden új gyerek csomópont ilyen tagját a szülőé+1 értékre állíthatnánk. De ezt nem akarjuk, mert a fa szerkezetében ott a mélység, nem akarjuk majd külön csomópontonként tárolni. S ugye esetünkben a gyökérben lévő mélységben amúgy is a teljes fa mélységét tároljuk. Illetve az atomhackerek munkája nyomán (C-beli) globális nélkül is meg tudjuk majd írni a bejárást.

Lehúzunk majd még pár bőrt erről a példáról, de nem ma. Olyan objektum lenne jó, ami teljesen elrejtené a korábbi C-s progi logikáját (ami tk. az algoritmus, az LZW fa építésének logikája) mondjuk csak "<<" operátorral kéne belenyomni az inputról bejövő betűket az LZW fa objektumba, nem?

Szólj hozzá!

Címkék: osztály class struktúra adatabsztrakció

A bejegyzés trackback címe:

https://progpater.blog.hu/api/trackback/id/tr872788175

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Nincsenek hozzászólások.
süti beállítások módosítása