Delcom - Ukážka stavového automatu v C
Ide o jednoduchú aplikáciu, ktorá odstraňuje zo vstupného textu Céčkové komentáre (/ * * / a //). Je to jeden z vzorových programov k článkom o filtroch, ktoré sa tu v budúcnosti objavia.
Pracuje so štandardným vstupom / výstupom, takže ak ju chceme použiť na súbory, urobíme to nasledujúcim spôsobom:
$ ./delcom < vstup.c > vystup.c
K programu som tiež napísal jednoduchý bash skript, ktorý spustí program pre každý .c súbor v priečinku. Samotný program je plne multiplatformový (a skript pre Windows nie je ťažké napísať). Inak či vás nenapadá žiadne praktické využitie, tak to skúste spustiť kolegovi programátorovi v nejakom rozsiahlom projekte (a dúfajte, že má zálohu, pretože inak vás zabije )
Stavový automat
Teraz tá zaujímavejšia časť .. Program slúži ako praktická ukážka použitia tzv. Stavového automatu - program, ktorý na základe aktuálneho stavu a vstupu vykoná konkrétnu úlohu. Stavový automat má určitý počet stavov, počiatočný stav, konečný stav, množinu vstupov a množinu výstupov. V praxi to znamená, že niekde začíname (najčastejšie stav 0) a na základe rôzneho vstupe sa prepína do iných stavov (napríklad používateľ zadá číslo -> umocní ho a vypiše, prejdi do stavu 2). Rôzne stavy reagujú na rovnaký vstup inak. Prečo stavový automat? Pozrieme sa na našu úlohu ..
Úlohou je napísať program, ktorý z textu odstráni Céčkové komentáre. Najprv sa musíme zamyslieť, ako vôbec komentáre v C fungujú.
- lomítko a hviezdička - začína blokový komentár (/ * * /)
- lomítko a lomka - začína riadkový komentár (//)
- úvodzovky - reťazcový literál, jeho obsah sa nesmie zmeniť (pozor na \ ")
- úvodzovky sa môžu objaviť aj ako znak! (Medzi apostrofy)
- komentáre sú nahradené medzerou
Nevyzerá to tak zložito, že? Ale nezabudnime, že komentáre nemusí byť zapísané rozumne ... Čo napríklad:
a = b //* tady dělím */c;
Vyzerá to škaredo, ale je to úplne validný použitia komentáre. Po odstránení komentárov preprocesoru bude výsledok nasledujúce:
a = b / c;
EDIT: Takéto použitie komentáre je validný iba pri použití C89 (ANSI), od C99 výška je už zvyšok riadku braný ako komentár ..
Tak to sme si snáď vymenovali všetky možnosti (snáď som na nič nezabudol). Teraz implementácie. Keď sa zamyslíme nad problémom, mohli by sme samozrejme použiť if-else. Ale veľmi skoro by sme zistili, že je to veľmi zložité a neprehľadné (či sa vám niekomu chce, tak to určite môžete skúsiť a potom porovnáme kód). Preto to budeme realizovať ako stavový automat.
Tu je schéma (.odg a .pdf verzie priložená v archíve):
Ak ste nikdy nič také nevideli, tak vám to určite pripadá ako neprehľadná a zložitá šialenosť. Ale v skutočnosti na tom nič komplikovaného nie je. "Kolieska" sú stavy a šípky medzi nimi ukazujú, ako sa mení. Pri každej šípky je poznámka, ktorá hovorí aký je vstup a (voliteľne) výstup.
Ukážeme si to na praktickom príklade. Keď sme v počiatočnom stave (stav 0) a na vstupe sa objaví úvodzovky, program sa prepne do stavu 4 a vypíše úvodzovky. Potom vypisuje akékoľvek prichádzajúce znaky (c out (c)), než sa zas objaví úvodzovky. Ak by sa objavilo spätné lomítko, existuje možnosť, že za ním budú úvodzovky, musíme preto do stavu 9, ktorý vypíše akýkoľvek znak nachádzajúci sa za lomkou. Keď sa konečne objavia normálne úvodzovky, sú vypísané a program je prepnutý do stavu 0. Analogicky to platí pre stav 7, ale namiesto úvodzovky riešime apostrof.
Rovnako tak druhý smer - ak na vstup príde lomka (ak čokoľvek iné, len sa to vypíše a zostávame v stave 0), presunieme sa do stavu 1 (tentoraz nevypíše nič). Ak nám teraz príde hviezdička, je jasné, že začína komentár -> presúvame sa do stavu 2 a až do konca komentáre všetko natierame (len to prečítame a nevypíše). Ak príde iný znak, vypíšeme lomítko a ten znak (lomítko bolo v tomto prípade delenia) a vrátime sa do stavu 0. Ak príde ďalšia lomítko, prepneme sa do stavu 5. Ak potom príde hviezdička, jedná sa o delené a komentár, ak čokoľvek iné, jedná sa o riadkový komentár, presúvame sa do stavu 6 a odstraňujeme všetko až do konca riadku. Ak by sme náhodou mali iba komentár a za ním hneď koniec riadku, ideme rovno do stavu 0.
Tak ... To je snáď všetko. Zdrojové kódy sú priložené v archíve. Ak chcete, určite si to môžete skompilovať pre Windows. Akékoľvek reakcia samozrejme uvítam ..
Poznámka: Alternatívne verzia, ktorá sa chová rôzne pre C89 a C99 je v komentároch.
Galéria
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 148x (131.79 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C