Virtuální souborový systém

Petr Sklenička       06.06.2010       C++/C       11568 zobrazení

Článek pojednává o způsobu návrhu virtuálního souborového systému. Před čtením Vám doporučuji stáhnout si a přečíst zadání, abyste věděli o co vlastně jde. Ke stažení jsou i zdrojové kódy v jazyce C++. Aplikace asi nemá žádné velké využití, nicméně přišlo mi to jako zajímavý problém - jednalo se o semestrální projekt.


Úvod

Úvodem bych chtěl podotknout, že tento článek neslouží jako nějaký tutoriál k jazyku C++, čili nebude zde vysvětleno, co dělají některá klíčová slova apod. Pokusím se klást důraz na vysvětlení způsobu návrhu, což znamená, že ten, kdo umí programovat v nějakém jiném jazyce, bude v tomto jazyce schopen program se stejným návrhem napsat. Jinak řečeno, mým cílem je vysvětlit logiku celého problému.

Struktura v paměti

Předpokládám, že jste si již přečetli zadání a víte tedy, co se od programu očekává. Jen pro připomenutí, jedná se o virtuální souborový systém (dále jen VSS), který pracuje s adresáři a textovými soubory. Celý systém je reprezentován pouze v paměti, čili nepracuje s pevným diskem počítače. Znamená to tedy, že v paměti se bude vytvářet jakási struktura, lépe řečeno stromová struktura. Vzhledem k tomu, že počet položek v nějakém adresáři není omezen, nelze tedy použít například binární strom. Nelze vlastně použít žádný strom, kde dopředu známe počet potomků nějakého uzlu. Nabízí se tedy tzv. n-ární strom.

Návrh tříd

Jak tedy začít? Již jsem se zmínil, že souborový systém pracuje s adresáři a textovými soubory, proto se nabízí vytvoření tříd Directory a File (nebo chcete-li Adresář a Soubor). Co se týče členských proměnných a metod jednotlivých tříd, dostanu se k nim za chvíli. Další otázkou je, jak zajistit, aby bylo možné s adresáři a soubory zacházet jednotným způsobem. Odpověď je snadná - stačí ke třídám Directory a File vytvořit nějakou bázovou třídu, v mém případě jde o třídu s názvem BaseObject. Tato třída obsahuje všechny metody, které adresář a soubor potřebují (např. přidání nového adresáře, vypsání obsahu souboru atd.). Metody této třídy jsou čistě virtuální, což má za následek, že není možné vytvořit objekt této třídy, je však možné vytvořit pointer (ukazatel). To je velmi důležité, protože celý program funguje na základě ukazatelů. Ve funkci Main je vytvořen kořenový adresář, na který po spuštění programu ukazuje ukazatel s názvem currentPath. Tento ukazatel je velmi důležitý, neboť po celou dobu ukazuje na aktuální adresář, ve kterém se právě nacházíme. Při startu programu je to tedy kořenový adresář, ale při zadávání jednotlivých příkazů se tento ukazatel mění dle potřeby.

Třída Directory

Zaměřme se nyní blíže na třídu Directory. Každý adresář má mít nějaké svoje jméno, datum a čas vytvoření. Je tedy jasné, že toto budou členské proměnné. Vzhledem k tomu, že soubor také má své jméno, datum a čas vytvoření, je možné tyto proměnné přidat do třídy BaseObject a třídy Directory a File je zdědí. Další věcí, kterou je nutno vyřešit, je způsob, jak zajistit, aby si každý adresář pamatoval, co obsahuje. Tento problém jsem vyřešil třídou List, která představuje seznam položek, uložených v adresáři. Je samozřejmé, že objekty této třídy má každý adresář, počínaje kořenovým.

Třída List

Třída List obsahuje celkem čtyři ukazatele - next, previous, parrent, item. Ukazatel parrent ukazuje na adresář, ve kterém se daná instance třídy List nachází, jinak řečeno, ukazuje na nadřazený adresář. Toho se využívá při zjišťování plné cesty nějakého adresáře, kdy se rekurzivně zjišťuje nadřazený adresář až do doby, než se dojde ke kořenovému adresáři. Ukazatele next a previous ukazují na další, respektive předchozí objekt třídy List. Zbývá ukazatel item - ten ukazuje buď na adresář, nebo soubor. Nově vytvořený adresář tedy obsahuje jednu instanci třídy List, přičemž ukazatele next, previous a item mají hodnotu NULL, jelikož právě vytvořený adresář je prázdný. Při přidání první položky (položkou se rozumí adresář nebo soubor) se inicializuje ukazatel item, čili ukazuje na právě přidanou položku. Ukazatele next a previous mají stále hodnotu NULL. Pokud dojde k přidání další položky, vytvoří se nová instance třídy List, na kterou ukazuje ukazatel next. Tato nová instance opět obsahuje všechny čtyři ukazatele, kde item ukazuje na druhou přidanou položku, previous na předchozí objekt třídy List a next má zatím hodnotu NULL (v adresáři jsou teprve dvě položky). Řekneme-li to velmi laicky a jednoduše, třída List je jakási krabička, ve které je právě jedna položka a každá krabička ví, kde je další a předchozí krabička. Všechny tyto krabičky jsou v jedné velké krabici, čímž je samozřejmě myšlen nadřazený adresář.

Metody třídy List

Práce s celým VSS probíhá na základě uživatelem zadaných příkazů. Každému příkazu odpovídá nějaká metoda třídy List. Třída Directory má také tyto metody, ty však nedělají nic jiného, než že volají patřičné metody třídy List. Většinu metod zde vysvětlovat nebudu, neboť si myslím, že nejsou tak složité, abyste je nedokázali pochopit sami.

Za zmínku stojí snad jen metoda ListChangePath, která umožňuje pohyb v celém VSS (volá se při příkazu cd). Tato metoda přebírá jako parametry ukazatel na adresář, ve kterém se právě nacházíme, a samozřejmě relativní cestu, kam se chceme dostat. Z relativní cesty si metoda zjistí první adresář (cesta je např. Texty/Dopisy/Soukromé, první adresář je tedy ten s názvem Texty) a vyhledá jej v daném adresáři. Pokud nebude hledání úspěšné, metoda vypíše chybovou hlášku a vrátí NULL. V opačném případě vrátí ukazatel na adresář Texty a celá metoda se volá rekurzivně, kde prvním parametrem bude právě onen ukazatel na Texty a relativní cesta bude už jen Dopisy/Soukromé. Není těžké si domyslet, že rekurze končí, pokud jsme úspěšně našli všechny adresáře v relativní cestě, tudíž metoda vrátí ukazatel na poslední vyhledávaný adresář (v našem případě Soukromé), čímž je dokončen pomyslný přesun v celém souborovém systému.

Třída File

Nyní zbývá jen krátký popis třídy File. Tato třída obsahuje všechny metody, které má adresář, protože je dědí z třídy BaseObject. Tyto metody je nutné přepsat, protože jinak by třída File byla abstraktní, čili by nebylo možné vytvořit žádný objekt této třídy. Samozřejmostí je, že se souborem není možné pracovat jako s adresářem, proto jsou metody přepsány tak, aby nic nedělaly. K jejich volání v programu však nikdy nedojde, proto to nevadí.

Závěr

Pokud jste si kód sami prošli, určitě jste si všimli, že jsem zde nezmínil úplně všechno. Jak jsem ale již v úvodu psal, šlo hlavně o způsob návrhu. Netvrdím, že kód je napsán úplně přesně podle mých představ, některé věci by ještě určitě šly vylepšit, proto budu rád za každou připomínku.

 

hodnocení článku

5 bodů / 7 hlasů       Hodnotit mohou jen registrované uživatelé.

 

Mohlo by vás také zajímat

C++ krok za krokem - díl 4.: Relační operátory a podmínky, příkaz switch

V dnešním díle se seznámíme s relačními a logickými operátory a naučíme se podmínky (příkaz if). Dále si ukážeme příkaz switch a na konci dílu si opět napíšeme krátký program.

C++ krok za krokem - díl 6.: Cykly, neboli smyčky

Po pauze větší, než je obvyklé, opět přichází další díl seriálu C++ krok za krokem. Všem čtenářům tohoto seriálu se za pauzu omlouvám, byla způsobena mými zdravotními problémy. V dnešním díle nás čeká úvod do smyček, neboli do cyklů. Představíme si cyklus for, vysvětlíme si co dělá a samozřejmě nebude chybět krátký příklad praktického užití. Jako bonus přikládám tři otázky, podle kterých si můžeme ověřit, jestli cyklům for rozumíte. V další díle si pak řekneme o druhém typu cyklů, konkrétně while.

C++ krok za krokem - díl 7.: Cykly, neboli smyčky - pokračování

V tomto díle si dovysvětlíme cykly. V minulém díle jsme se zaměřili na cykly for, dnes to bude o cyklech while. Vysvětlíme si tedy, jaký je mezi nimi rozdíl, ukážeme si, jaká je syntaxe cyklu while a nebude chybět ani krátký příklad na závěr.

 

 

Nový příspěvek

 

                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback