Advertisement
Guest User

Untitled

a guest
Mar 26th, 2013
52
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 22.40 KB | None | 0 0
  1. // z3a7.cpp
  2. //
  3. // Együtt támadjuk meg: http://progpater.blog.hu/2011/04/14/egyutt_tamadjuk_meg
  4. // LZW fa építő 3. C++ átirata a C valtozatbol (+mélység, atlag és szórás)
  5. // Programozó Páternoszter
  6. //
  7. // Copyright (C) 2011, 2012, Bátfai Norbert, nbatfai@inf.unideb.hu, nbatfai@gmail.com
  8. //
  9. // This program is free software: you can redistribute it and/or modify
  10. // it under the terms of the GNU General Public License as published by
  11. // the Free Software Foundation, either version 3 of the License, or
  12. // (at your option) any later version.
  13. //
  14. // This program is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. // GNU General Public License for more details.
  18. //
  19. // You should have received a copy of the GNU General Public License
  20. // along with this program.  If not, see <http://www.gnu.org/licenses/>.
  21. //
  22. // Ez a program szabad szoftver; terjeszthetõ illetve módosítható a
  23. // Free Software Foundation által kiadott GNU General Public License
  24. // dokumentumában leírtak; akár a licenc 3-as, akár (tetszõleges) késõbbi
  25. // változata szerint.
  26. //
  27. // Ez a program abban a reményben kerül közreadásra, hogy hasznos lesz,
  28. // de minden egyéb GARANCIA NÉLKÜL, az ELADHATÓSÁGRA vagy VALAMELY CÉLRA
  29. // VALÓ ALKALMAZHATÓSÁGRA való származtatott garanciát is beleértve.
  30. // További részleteket a GNU General Public License tartalmaz.
  31. //
  32. // A felhasználónak a programmal együtt meg kell kapnia a GNU General
  33. // Public License egy példányát; ha mégsem kapta meg, akkor
  34. // tekintse meg a <http://www.gnu.org/licenses/> oldalon.
  35. //
  36. //
  37. // Version history:
  38. //
  39. // 0.0.1,       http://progpater.blog.hu/2011/02/19/gyonyor_a_tomor
  40. // 0.0.2,       csomópontok mutatóinak NULLázása (nem fejtette meg senki :)
  41. // 0.0.3,       http://progpater.blog.hu/2011/03/05/labormeres_otthon_avagy_hogyan_dolgozok_fel_egy_pedat
  42. // 0.0.4,       z.cpp: a C verzióból svn: bevezetes/C/ziv/z.c átírjuk C++-ra
  43. //              http://progpater.blog.hu/2011/03/31/imadni_fogjatok_a_c_t_egy_emberkent_tiszta_szivbol
  44. // 0.0.5,       z2.cpp: az fgv(*mut)-ok helyett fgv(&ref)
  45. // 0.0.6,       z3.cpp: Csomopont beágyazva
  46. //              http://progpater.blog.hu/2011/04/01/imadni_fogjak_a_c_t_egy_emberkent_tiszta_szivbol_2
  47. // 0.0.6.1      z3a2.c: LZWBinFa már nem barátja a Csomopont-nak, mert annak tagjait nem használja direktben
  48. // 0.0.6.2      Kis kommentezést teszünk bele 1. lépésként (hogy a kicsit lemaradt hallgatóknak is
  49. //              könnyebb legyen, jól megtűzdeljük további olvasmányokkal)
  50. //              http://progpater.blog.hu/2011/04/14/egyutt_tamadjuk_meg
  51. //              (majd a 2. lépésben "beletesszük a d.c-t", majd s 3. lépésben a parancssorsor argok feldolgozását)
  52. // 0.0.6.3      z3a2.c: Fejlesztgetjük a forrást: http://progpater.blog.hu/2011/04/17/a_tizedik_tizenegyedik_labor
  53. // 0.0.6.4      SVN-beli, http://www.inf.unideb.hu/~nbatfai/p1/forrasok-SVN/bevezetes/vedes/
  54. // 0.0.6.5      2012.03.20, z3a4.cpp: N betűk (hiányok), sorvégek, vezetÅ‘ komment figyelmen kívül: http://progpater.blog.hu/2012/03/20/a_vedes_elokeszitese
  55. // 0.0.6.6      z3a5.cpp: mamenyaka kolléga észrevételére a több komment sor figyelmen kívül hagyása
  56. //      http://progpater.blog.hu/2012/03/20/a_vedes_elokeszitese/fullcommentlist/1#c16150365
  57. // 0.0.6.7  Javaslom ezt a verziót választani védendÅ‘ programnak
  58. // 0.0.6.8  z3a7.cpp: pár kisebb javítás, illetve a védések támogatásához további komment a <<
  59. //      eltoló operátort tagfüggvényként, illetve globális függvényként túlterhelÅ‘ részekhez.
  60. //      http://progpater.blog.hu/2012/04/10/imadni_fogjak_a_c_t_egy_emberkent_tiszta_szivbol_4/fullcommentlist/1#c16341099
  61. //
  62.  
  63. #include <iostream>     // mert olvassuk a std::cin, írjuk a std::cout csatornákat
  64. #include <cmath>        // mert vonunk gyököt a szóráshoz: std::sqrt
  65. #include <fstream>      // fájlból olvasunk, írunk majd
  66.  
  67. /* Az LZWBinFa osztályban absztraháljuk az LZW algoritmus bináris fa építését. Az osztály
  68.  definíciójába beágyazzuk a fa egy csomópontjának az absztrakt jellemzését, ez lesz a
  69.  beágyazott Csomopont osztály. Miért ágyazzuk be? Mert külön nem szánunk neki szerepet, ezzel
  70.  is jelezzük, hogy csak a fa részeként számiolunk vele.*/
  71.  
  72. class LZWBinFa
  73. {
  74. public:
  75.   /* Szemben a bináris keresÅ‘fánkkal (BinFa osztály)
  76.      http://progpater.blog.hu/2011/04/12/imadni_fogjak_a_c_t_egy_emberkent_tiszta_szivbol_3
  77.      itt (LZWBinFa osztály) a fa gyökere nem pointer, hanem a '/' betüt tartalmazó objektum,
  78.      lásd majd a védett tagok között lent: Csomopont gyoker;
  79.      A fa viszont már pointer, mindig az épülÅ‘ LZW-fánk azon csomópontjára mutat, amit az
  80.      input feldolgozása során az LZW algoritmus logikája diktál:
  81.      http://progpater.blog.hu/2011/02/19/gyonyor_a_tomor
  82.      Ez a konstruktor annyit csinál, hogy a fa mutatót ráállítja a gyökérre. (Mert ugye
  83.      laboron, blogon, elÅ‘adásban tisztáztuk, hogy a tartalmazott tagok, most "Csomopont gyoker"
  84.      konstruktora elÅ‘bb lefut, mint a tagot tartalmazó LZWBinFa osztály konstruktora, éppen a
  85.      következÅ‘, azaz a fa=&gyoker OK.)
  86.    */
  87.   LZWBinFa ():fa (&gyoker)
  88.   {
  89.   }
  90.    ~LZWBinFa ()
  91.   {
  92.     szabadit (gyoker.egyesGyermek ());
  93.     szabadit (gyoker.nullasGyermek ());
  94.   }
  95.  
  96.   /* Tagfüggvényként túlterheljük a << operátort, ezzel a célunk, hogy felkeltsük a
  97.      hallgató érdeklÅ‘dését, mert ekkor így nyomhatjuk a fába az inputot: binFa << b; ahol a b
  98.      egy '0' vagy '1'-es betű.
  99.      Mivel tagfüggvény, így van rá "értelmezve" az aktuális (this "rejtett paraméterként"
  100.      kapott ) példány, azaz annak a fának amibe éppen be akarjuk nyomni a b betűt a tagjai
  101.      (pl.: "fa", "gyoker") használhatóak a függvényben.
  102.  
  103.      A függvénybe programoztuk az LZW fa építésének algoritmusát tk.:
  104.      http://progpater.blog.hu/2011/02/19/gyonyor_a_tomor
  105.  
  106.      a b formális param az a betű, amit éppen be kell nyomni a fába.
  107.      
  108.      a binFa << b (ahol a b majd a végén látszik, hogy már az '1' vagy a '0') azt jelenti
  109.      tagfüggvényként, hogy binFa.operator<<(b) (globálisként így festene: operator<<(binFa, b) )
  110.          
  111.      */
  112.   void operator<< (char b)
  113.   {
  114.     // Mit kell betenni éppen, '0'-t?
  115.     if (b == '0')
  116.       {
  117.     /* Van '0'-s gyermeke az aktuális csomópontnak?
  118.        megkérdezzük TÅ‘le, a "fa" mutató éppen reá mutat */
  119.     if (!fa->nullasGyermek ())  // ha nincs, hát akkor csinálunk
  120.       {
  121.         // elkészítjük, azaz páldányosítunk a '0' betű akt. parammal
  122.         Csomopont *uj = new Csomopont ('0');
  123.         // az aktuális csomópontnak, ahol állunk azt üzenjük, hogy
  124.         // jegyezze már be magának, hogy nullás gyereke mostantól van
  125.         // küldjük is Neki a gyerek címét:
  126.         fa->ujNullasGyermek (uj);
  127.         // és visszaállunk a gyökérre (mert ezt diktálja az alg.)
  128.         fa = &gyoker;
  129.       }
  130.     else            // ha van, arra rálépünk
  131.       {
  132.         // azaz a "fa" pointer már majd a szóban forgó gyermekre mutat:
  133.         fa = fa->nullasGyermek ();
  134.       }
  135.       }
  136.     // Mit kell betenni éppen, vagy '1'-et?
  137.     else
  138.       {
  139.     if (!fa->egyesGyermek ())
  140.       {
  141.         Csomopont *uj = new Csomopont ('1');
  142.         fa->ujEgyesGyermek (uj);
  143.         fa = &gyoker;
  144.       }
  145.     else
  146.       {
  147.         fa = fa->egyesGyermek ();
  148.       }
  149.       }
  150.   }
  151.   /* A bejárással kapcsolatos függvényeink (túlterhelt kiir-ók, atlag, ratlag stb.) rekurzívak,
  152.      tk. a rekurzív fabejárást valósítják meg (lásd a 3. elÅ‘adás "Fabejárás" c. fóliáját és társait)
  153.  
  154.      (Ha a rekurzív függvénnyel általában gondod van => K&R könyv megfelelÅ‘ része: a 3. ea. izometrikus
  155.      részében ezt "letáncoltuk" :) és külön idéztük a K&R álláspontját :)
  156.    */
  157.   void kiir (void)
  158.   {
  159.     // Sokkal elegánsabb lenne (és más, a bevezetésben nem kibontandó reentráns kérdések miatt is, mert
  160.     // ugye ha most két helyrÅ‘l hívják meg az objektum ilyen függvényeit, tahát ha kétszer kezd futni az
  161.     // objektum kiir() fgv.-e pl., az komoly hiba, mert elromlana a mélység... tehát a mostani megoldásunk
  162.     // nem reentráns) ha nem használnánk a C verzióban globális változókat, a C++ változatban példánytagot a
  163.     // mélység kezelésére: http://progpater.blog.hu/2011/03/05/there_is_no_spoon
  164.     melyseg = 0;
  165.     // ha nem mondta meg a hívó az üzenetben, hogy hova írjuk ki a fát, akkor a
  166.     // sztenderd out-ra nyomjuk
  167.     kiir (&gyoker, std::cout);
  168.   }
  169.   /* már nem használjuk, tartalmát a dtor hívja
  170.   void szabadit (void)
  171.   {
  172.     szabadit (gyoker.egyesGyermek ());
  173.     szabadit (gyoker.nullasGyermek ());
  174.     // magát a gyökeret nem szabadítjuk, hiszen azt nem mi foglaltuk a szabad tárban (halmon).
  175.   }
  176.   */
  177.  
  178.   /* A változatosság kedvéért ezeket az osztálydefiníció (class LZWBinFa {...};) után definiáljuk,
  179.      hogy kénytelen légy az LZWBinFa és a :: hatókör operátorral minÅ‘sítve definiálni :) l. lentebb */
  180.   int getMelyseg (void);
  181.   double getAtlag (void);
  182.   double getSzoras (void);
  183.  
  184.   /* Vágyunk, hogy a felépített LZW fát ki tudjuk nyomni ilyenformán: std::cout << binFa;
  185.      de mivel a << operátor is a sztenderd névtérben van, de a using namespace std-t elvbÅ‘l
  186.      nem használjuk bevezetÅ‘ kurzusban, így ez a konstrukció csak az argfüggÅ‘ névfeloldás miatt
  187.      fordul le (B&L könyv 185. o. teteje) ám itt nem az a lényeg, hanem, hogy a cout ostream
  188.      osztálybeli, így abban az osztályban kéne módosítani, hogy tudjon kiírni LZWBinFa osztálybelieket...
  189.      e helyett a globális << operátort terheljük túl,
  190.      
  191.      a kiFile << binFa azt jelenti, hogy
  192.      
  193.       - tagfüggvényként: kiFile.operator<<(binFa) de ehhez a kiFile valamilyen
  194.       std::ostream stream osztály forrásába kellene beleírni ezt a tagfüggvényt,
  195.       amely ismeri a mi LZW binfánkat...
  196.      
  197.       - globális függvényként: operator<<(kiFile, binFa) és pont ez látszik a következÅ‘ sorban:
  198.      
  199.      */
  200.   friend std::ostream & operator<< (std::ostream & os, LZWBinFa & bf)
  201.   {
  202.     bf.kiir (os);
  203.     return os;
  204.   }
  205.   void kiir (std::ostream & os)
  206.   {
  207.     melyseg = 0;
  208.     kiir (&gyoker, os);
  209.   }
  210.  
  211. private:
  212.   class Csomopont
  213.   {
  214.   public:
  215.     /* A paraméter nélküli konstruktor az elepértelmezett '/' "gyökér-betűvel" hozza
  216.        létre a csomópontot, ilyet hívunk a fából, aki tagként tartalmazza a gyökeret.
  217.        Máskülönben, ha valami betűvel hívjuk, akkor azt teszi a "betu" tagba, a két
  218.        gyermekre mutató mutatót pedig nullra állítjuk, C++-ban a 0 is megteszi. */
  219.   Csomopont (char b = '/'):betu (b), balNulla (0), jobbEgy (0)
  220.     {
  221.     };
  222.     ~Csomopont ()
  223.     {
  224.     };
  225.     // Aktuális csomópont, mondd meg nékem, ki a bal oldali gyermeked
  226.     // (a C verzió logikájával műxik ez is: ha nincs, akkor a null megy vissza)
  227.     Csomopont *nullasGyermek () const
  228.     {
  229.       return balNulla;
  230.     }
  231.     // Aktuális csomópon,t mondd meg nékem, ki a jobb oldali gyermeked?
  232.     Csomopont *egyesGyermek () const
  233.     {
  234.       return jobbEgy;
  235.     }
  236.     // Aktuális csomópont, ímhol legyen a "gy" mutatta csomópont a bal oldali gyereked!
  237.     void ujNullasGyermek (Csomopont * gy)
  238.     {
  239.       balNulla = gy;
  240.     }
  241.     // Aktuális csomópont, ímhol legyen a "gy" mutatta csomópont a jobb oldali gyereked!
  242.     void ujEgyesGyermek (Csomopont * gy)
  243.     {
  244.       jobbEgy = gy;
  245.     }
  246.     // Aktuális csomópont: Te milyen betűt hordozol?
  247.     // (a const kulcsszóval jelezzük, hogy nem bántjuk a példányt)
  248.     char getBetu () const
  249.     {
  250.       return betu;
  251.     }
  252.  
  253.   private:
  254.     // friend class LZWBinFa; /* mert ebben a valtozatban az LZWBinFa metódusai nem közvetlenül
  255.     // a Csomopont tagjaival dolgoznak, hanem beállító/lekérdezÅ‘ üzenetekkel érik el azokat */
  256.  
  257.     // Milyen betűt hordoz a csomópont
  258.     char betu;
  259.     // Melyik másik csomópont a bal oldali gyermeke? (a C változatból "örökölt" logika:
  260.     // ha hincs ilyen csermek, akkor balNulla == null) igaz
  261.     Csomopont *balNulla;
  262.     Csomopont *jobbEgy;
  263.     // nem másolható a csomópont (ökörszabály: ha van valamilye a szabad tárban,
  264.     // letiltjuk a másoló konstruktort, meg a másoló értékadást)
  265.     Csomopont (const Csomopont &);
  266.     Csomopont & operator= (const Csomopont &);
  267.   };
  268.  
  269.   /* Mindig a fa "LZW algoritmus logikája szerinti aktuális" csomópontjára mutat */
  270.   Csomopont *fa;
  271.   // technikai
  272.   int melyseg, atlagosszeg, atlagdb;
  273.   double szorasosszeg;
  274.   // szokásosan: nocopyable
  275.   LZWBinFa (const LZWBinFa &);
  276.   LZWBinFa & operator= (const LZWBinFa &);
  277.  
  278.   /* Kiírja a csomópontot az os csatornára. A rekurzió kapcsán lásd a korábbi K&R-es utalást... */
  279.   void kiir (Csomopont * elem, std::ostream & os)
  280.   {
  281.     // Nem létezÅ‘ csomóponttal nem foglalkozunk... azaz ez a rekurzió leállítása
  282.     if (elem != NULL)
  283.       {
  284.     ++melyseg;
  285.     kiir (elem->egyesGyermek (), os);
  286.     // ez a postorder bejáráshoz képest
  287.     // 1-el nagyobb mélység, ezért -1
  288.     for (int i = 0; i < melyseg; ++i)
  289.       os << "---";
  290.     os << elem->getBetu () << "(" << melyseg - 1 << ")" << std::endl;
  291.     kiir (elem->nullasGyermek (), os);
  292.     --melyseg;
  293.       }
  294.   }
  295.   void szabadit (Csomopont * elem)
  296.   {
  297.     // Nem létezÅ‘ csomóponttal nem foglalkozunk... azaz ez a rekurzió leállítása
  298.     if (elem != NULL)
  299.       {
  300.     szabadit (elem->egyesGyermek ());
  301.     szabadit (elem->nullasGyermek ());
  302.     // ha a csomópont mindkét gyermekét felszabadítottuk
  303.     // azután szabadítjuk magát a csomópontot:
  304.     delete elem;
  305.       }
  306.   }
  307.  
  308. protected:          // ha esetleg egyszer majd kiterjesztjük az osztályt, mert
  309. // akarunk benne valami újdonságot csinálni, vagy meglévő tevékenységet máshogy... stb.
  310. // akkor ezek látszanak majd a gyerek osztályban is
  311.  
  312.   /* A fában tagként benne van egy csomópont, ez erÅ‘sen ki van tüntetve, Ő a gyökér: */
  313.   Csomopont gyoker;
  314.   int maxMelyseg;
  315.   double atlag, szoras;
  316.  
  317.   void rmelyseg (Csomopont * elem);
  318.   void ratlag (Csomopont * elem);
  319.   void rszoras (Csomopont * elem);
  320.  
  321. };
  322.  
  323. // Néhány függvényt az osztálydefiníció után definiálunk, hogy lássunk ilyet is ... :)
  324. // Nem erőltetjük viszont a külön fájlba szedést, mert a sablonosztályosított tovább
  325. // fejlesztésben az linkelési gondot okozna, de ez a téma már kivezet a laborteljesítés
  326. // szükséges feladatából: http://progpater.blog.hu/2011/04/12/imadni_fogjak_a_c_t_egy_emberkent_tiszta_szivbol_3
  327.  
  328. // Egyébként a melyseg, atlag és szoras fgv.-ek a kiir fgv.-el teljesen egy kaptafa.
  329.  
  330. int
  331. LZWBinFa::getMelyseg (void)
  332. {
  333.   melyseg = maxMelyseg = 0;
  334.   rmelyseg (&gyoker);
  335.   return maxMelyseg - 1;
  336. }
  337.  
  338. double
  339. LZWBinFa::getAtlag (void)
  340. {
  341.   melyseg = atlagosszeg = atlagdb = 0;
  342.   ratlag (&gyoker);
  343.   atlag = ((double) atlagosszeg) / atlagdb;
  344.   return atlag;
  345. }
  346.  
  347. double
  348. LZWBinFa::getSzoras (void)
  349. {
  350.   atlag = getAtlag ();
  351.   szorasosszeg = 0.0;
  352.   melyseg = atlagdb = 0;
  353.  
  354.   rszoras (&gyoker);
  355.  
  356.   if (atlagdb - 1 > 0)
  357.     szoras = std::sqrt (szorasosszeg / (atlagdb - 1));
  358.   else
  359.     szoras = std::sqrt (szorasosszeg);
  360.  
  361.   return szoras;
  362. }
  363.  
  364. void
  365. LZWBinFa::rmelyseg (Csomopont * elem)
  366. {
  367.   if (elem != NULL)
  368.     {
  369.       ++melyseg;
  370.       if (melyseg > maxMelyseg)
  371.     maxMelyseg = melyseg;
  372.       rmelyseg (elem->egyesGyermek ());
  373.       // ez a postorder bejáráshoz képest
  374.       // 1-el nagyobb mélység, ezért -1
  375.       rmelyseg (elem->nullasGyermek ());
  376.       --melyseg;
  377.     }
  378. }
  379.  
  380. void
  381. LZWBinFa::ratlag (Csomopont * elem)
  382. {
  383.   if (elem != NULL)
  384.     {
  385.       ++melyseg;
  386.       ratlag (elem->egyesGyermek ());
  387.       ratlag (elem->nullasGyermek ());
  388.       --melyseg;
  389.       if (elem->egyesGyermek () == NULL && elem->nullasGyermek () == NULL)
  390.     {
  391.       ++atlagdb;
  392.       atlagosszeg += melyseg;
  393.     }
  394.     }
  395. }
  396.  
  397. void
  398. LZWBinFa::rszoras (Csomopont * elem)
  399. {
  400.   if (elem != NULL)
  401.     {
  402.       ++melyseg;
  403.       rszoras (elem->egyesGyermek ());
  404.       rszoras (elem->nullasGyermek ());
  405.       --melyseg;
  406.       if (elem->egyesGyermek () == NULL && elem->nullasGyermek () == NULL)
  407.     {
  408.       ++atlagdb;
  409.       szorasosszeg += ((melyseg - atlag) * (melyseg - atlag));
  410.     }
  411.     }
  412. }
  413.  
  414. // teszt pl.: http://progpater.blog.hu/2011/03/05/labormeres_otthon_avagy_hogyan_dolgozok_fel_egy_pedat
  415. // [norbi@sgu ~]$ echo "01111001001001000111"|./z3a2
  416. // ------------1(3)
  417. // ---------1(2)
  418. // ------1(1)
  419. // ---------0(2)
  420. // ------------0(3)
  421. // ---------------0(4)
  422. // ---/(0)
  423. // ---------1(2)
  424. // ------0(1)
  425. // ---------0(2)
  426. // depth = 4
  427. // mean = 2.75
  428. // var = 0.957427
  429. // a laborvédéshez majd ezt a tesztelést használjuk:
  430. // http://
  431.  
  432. /* Ez volt eddig a main, de most komplexebb kell, mert explicite bejövő, kimenő fájlokkal kell dolgozni
  433. int
  434. main ()
  435. {
  436.     char b;
  437.     LZWBinFa binFa;
  438.  
  439.     while (std::cin >> b)
  440.     {
  441.         binFa << b;
  442.     }
  443.  
  444.     //std::cout << binFa.kiir (); // így rajzolt ki a fát a korábbi verziókban de, hogy izgalmasabb legyen
  445.     // a példa, azaz ki lehessen tolni az LZWBinFa-t kimeneti csatornára:
  446.  
  447.     std::cout << binFa; // ehhez kell a globális operator<< túlterhelése, lásd fentebb
  448.  
  449.     std::cout << "depth = " << binFa.getMelyseg () << std::endl;
  450.     std::cout << "mean = " << binFa.getAtlag () << std::endl;
  451.     std::cout << "var = " << binFa.getSzoras () << std::endl;
  452.  
  453.     binFa.szabadit ();
  454.  
  455.     return 0;
  456. }
  457. */
  458.  
  459. /* A parancssor arg. kezelést egyszerűen bedolgozzuk a 2. hullám kapcsolódó feladatából:
  460.  http://progpater.blog.hu/2011/03/12/hey_mikey_he_likes_it_ready_for_more_3
  461.  de mivel nekünk sokkal egyszerűbb is elég, alig hagyunk meg belÅ‘le valamit...
  462.  */
  463.  
  464. void
  465. usage (void)
  466. {
  467.   std::cout << "Usage: lzwtree in_file -o out_file" << std::endl;
  468. }
  469.  
  470. int
  471. main (int argc, char *argv[])
  472. {
  473.   // http://progpater.blog.hu/2011/03/12/hey_mikey_he_likes_it_ready_for_more_3
  474.   // alapján a parancssor argok ottani elegáns feldolgozásából kb. ennyi marad:
  475.   // "*((*++argv)+1)"...
  476.  
  477.   // a kiírás szerint ./lzwtree in_file -o out_file alakra kell mennie, ez 4 db arg:
  478.   if (argc != 4)
  479.     {
  480.       // ha nem annyit kapott a program, akkor felhomályosítjuk errÅ‘l a júzetr:
  481.       usage ();
  482.       // és jelezzük az operációs rendszer felé, hogy valami gáz volt...
  483.       return -1;
  484.     }
  485.  
  486.   // "Megjegyezzük" a bemenÅ‘ fájl nevét
  487.   char *inFile = *++argv;
  488.  
  489.   // a -o kapcsoló jön?
  490.   if (*((*++argv) + 1) != 'o')
  491.     {
  492.       usage ();
  493.       return -2;
  494.     }
  495.  
  496.   // ha igen, akkor az 5. elÅ‘adásból kimásoljuk a fájlkezelés C++ változatát:
  497.   std::fstream beFile (inFile, std::ios_base::in);
  498.  
  499.   // fejlesztgetjük a forrást: http://progpater.blog.hu/2011/04/17/a_tizedik_tizenegyedik_labor
  500.   if (!beFile)
  501.     {
  502.       std::cout << inFile << " nem letezik..." << std::endl;
  503.       usage ();
  504.       return -3;
  505.     }
  506.  
  507.   std::fstream kiFile (*++argv, std::ios_base::out);
  508.  
  509.   unsigned char b;      // ide olvassik majd a bejövÅ‘ fájl bájtjait
  510.   LZWBinFa binFa;       // s nyomjuk majd be az LZW fa objektumunkba
  511.  
  512.   // a bemenetet binárisan olvassuk, de a kimenÅ‘ fájlt már karakteresen írjuk, hogy meg tudjuk
  513.   // majd nézni... :) l. az említett 5. ea. C -> C++ gyökkettes átírási példáit
  514.  
  515.   while (beFile.read ((char *) &b, sizeof (unsigned char)))
  516.     if (b == 0x0a)
  517.       break;
  518.  
  519.   bool kommentben = false;
  520.  
  521.   while (beFile.read ((char *) &b, sizeof (unsigned char)))
  522.     {
  523.  
  524.       if (b == 0x3e)
  525.     {           // > karakter
  526.       kommentben = true;
  527.       continue;
  528.     }
  529.  
  530.       if (b == 0x0a)
  531.     {           // újsor
  532.       kommentben = false;
  533.       continue;
  534.     }
  535.  
  536.       if (kommentben)
  537.     continue;
  538.  
  539.       if (b == 0x4e)        // N betű
  540.     continue;
  541.  
  542.       // egyszerűen a korábbi d.c kódját bemásoljuk
  543.       // laboron többször lerajzoltuk ezt a bit-tologatást:
  544.       // a b-ben lévÅ‘ bájt bitjeit egyenként megnézzük
  545.       for (int i = 0; i < 8; ++i)
  546.     {
  547.       // maszkolunk eddig..., most már simán írjuk az if fejébe a legmagasabb helyiértékű bit vizsgálatát
  548.       // csupa 0 lesz benne a végén pedig a vizsgált 0 vagy 1, az if megmondja melyik:
  549.       if (b & 0x80)
  550.         // ha a vizsgált bit 1, akkor az '1' betűt nyomjuk az LZW fa objektumunkba
  551.         binFa << '1';
  552.       else
  553.         // különben meg a '0' betűt:
  554.         binFa << '0';
  555.       b <<= 1;
  556.     }
  557.  
  558.     }
  559.  
  560.   //std::cout << binFa.kiir (); // így rajzolt ki a fát a korábbi verziókban de, hogy izgalmasabb legyen
  561.   // a példa, azaz ki lehessen tolni az LZWBinFa-t kimeneti csatornára:
  562.  
  563.   kiFile << binFa;      // ehhez kell a globális operator<< túlterhelése, lásd fentebb
  564.   // (jó ez az OO, mert mi ugye nem igazán erre gondoltunk, amikor írtuk, mégis megy, hurrá)
  565.  
  566.   kiFile << "depth = " << binFa.getMelyseg () << std::endl;
  567.   kiFile << "mean = " << binFa.getAtlag () << std::endl;
  568.   kiFile << "var = " << binFa.getSzoras () << std::endl;
  569.  
  570.   kiFile.close ();
  571.   beFile.close ();
  572.  
  573.   return 0;
  574. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement