Advertisement
Guest User

Untitled

a guest
Nov 1st, 2014
149
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.12 KB | None | 0 0
  1.  
  2. /* ******************************* c203.c *********************************** */
  3. /*  Předmět: Algoritmy (IAL) - FIT VUT v Brně                                 */
  4. /*  Úkol: c203 - Fronta znaků v poli                                          */
  5. /*  Referenční implementace: Petr Přikryl, 1994                               */
  6. /*  Přepis do jazyka C: Václav Topinka, září 2005                             */
  7. /*  Úpravy: Bohuslav Křena, říjen 2014                                        */
  8. /* ************************************************************************** */
  9. /*
  10. ** Implementujte frontu znaků v poli. Přesnou definici typů naleznete
  11. ** v hlavičkovém souboru c203.h (ADT fronta je reprezentována strukturou tQueue,
  12. ** která obsahuje pole 'arr' pro uložení hodnot ve frontě a indexy f_index
  13. ** a b_index. Všechny implementované funkce musí předpokládat velikost pole
  14. ** QUEUE_SIZE, i když ve skutečnosti jsou rozměry statického pole definovány
  15. ** MAX_QUEUE. Hodnota QUEUE_SIZE slouží k simulaci fronty v různě velkém poli
  16. ** a nastavuje se v testovacím skriptu c203-test.c před testováním
  17. ** implementovaných funkcí. Hodnota QUEUE_SIZE může nabývat hodnot v rozsahu
  18. ** 1 až MAX_QUEUE.
  19. **
  20. ** Index f_index ukazuje vždy na první prvek ve frontě. Index b_index
  21. ** ukazuje na první volný prvek ve frontě. Pokud je fronta prázdná, ukazují
  22. ** oba indexy na stejné místo. Po inicializaci ukazují na první prvek pole,
  23. ** obsahují tedy hodnotu 0. Z uvedených pravidel vyplývá, že v poli je vždy
  24. ** minimálně jeden prvek nevyužitý.
  25. **
  26. ** Při libovolné operaci se žádný z indexů (f_index i b_index) nesnižuje
  27. ** vyjma případu, kdy index přesáhne hranici QUEUE_SIZE. V tom případě
  28. ** se "posunuje" znovu na začátek pole. Za tímto účelem budete deklarovat
  29. ** pomocnou funkci NextIndex, která pro kruhový pohyb přes indexy pole
  30. ** využívá operaci "modulo".
  31. **
  32. ** Implementujte následující funkce:
  33. **
  34. **    nextIndex ..... pomocná funkce - viz popis výše
  35. **    queueInit ..... inicializace fronty
  36. **    queueEmpty .... test na prázdnost fronty
  37. **    queueFull ..... test, zda je fronta zaplněna (vyčerpána kapacita)
  38. **    queueFront .... přečte hodnoty prvního prvku z fronty
  39. **    queueRemove ... odstraní první prvek fronty
  40. **    queueGet ...... přečte a odstraní první prvek fronty
  41. **    queueUp ....... zařazení prvku na konec fronty
  42. **
  43. ** Své řešení účelně komentujte!
  44. **
  45. ** Terminologická poznámka: Jazyk C nepoužívá pojem procedura.
  46. ** Proto zde používáme pojem funkce i pro operace, které by byly
  47. ** v algoritmickém jazyce Pascalovského typu implemenovány jako
  48. ** procedury (v jazyce C procedurám odpovídají funkce vracející typ void).
  49. **
  50. **/
  51.  
  52. #include "c203.h"
  53.  
  54. void queueError (int error_code) {
  55. /*
  56. ** Vytiskne upozornění na to, že došlo k chybě.
  57. ** Tato funkce bude volána z některých dále implementovaných operací.
  58. **
  59. ** TUTO FUNKCI, PROSÍME, NEUPRAVUJTE!
  60. */
  61.     static const char* QERR_STRINGS[MAX_QERR+1] = {"Unknown error","Queue error: UP","Queue error: FRONT","Queue error: REMOVE","Queue error: GET","Queue error: INIT"};
  62.     if ( error_code <= 0 || error_code > MAX_QERR )
  63.         error_code = 0;
  64.     printf ( "%s\n", QERR_STRINGS[error_code] );
  65.     err_flag = 1;
  66. }
  67.  
  68. void queueInit (tQueue* q) {
  69. /*
  70. ** Inicializujte frontu následujícím způsobem:
  71. ** - všechny hodnoty v poli q->arr nastavte na '*',
  72. ** - index na začátek fronty nastavte na 0,
  73. ** - index prvního volného místa nastavte také na 0.
  74. **
  75. ** V případě, že funkce dostane jako parametr q == NULL, volejte funkci
  76. ** queueError(QERR_INIT).
  77. */
  78.  
  79.     if (q == NULL)                  /* Pokud je seznam q == NULL, vrátíme požadovanou chybu */
  80.         queueError(QERR_INIT);
  81.     else
  82.     {
  83.         for (int I = 0; I < QUEUE_SIZE; I++)        /* Projdeme celý seznam a postupně přiřadíme na všechny pozice '*' */
  84.         {
  85.             q->arr[I] = '*';
  86.         }
  87.  
  88.         q->f_index = 0;                 /* Index na začátek fronty nastavíme na nulu */
  89.         q->b_index = 0;                 /* Index na první volné místo nastavíme též na nulu */
  90.     }
  91. }
  92.  
  93. int nextIndex (int index) {
  94. /*
  95. ** Pomocná funkce, která vrací index následujícího prvku v poli.
  96. ** Funkci implementujte jako jediný prikaz využívající operace '%'.
  97. ** Funkci nextIndex budete využívat v dalších implementovaných funkcích.
  98. */
  99.  
  100.     return ((index + 1) % QUEUE_SIZE);
  101. }
  102.  
  103. int queueEmpty (const tQueue* q) {
  104. /*
  105. ** Vrací nenulovou hodnotu, pokud je frona prázdná, jinak vrací hodnotu 0.
  106. ** Funkci implementujte jako jediný příkaz.
  107. */
  108.  
  109.     /* Použil jsem ternární operátory */
  110.     /* Pokud se pozice prvního prvku rovná zároveň pozici prvního prázdného místa, je seznam prázdný */
  111.     return ((q->f_index == q->b_index) ? 1 : 0);
  112. }
  113.  
  114. int queueFull (const tQueue* q) {
  115. /*
  116. ** Vrací nenulovou hodnotu, je-li fronra plná, jinak vrací hodnotu 0.
  117. ** Funkci implementujte jako jediný příkaz s využitím pomocné funkce nextIndex.
  118. */
  119.  
  120.     /* Použil jsem ternární operátory */
  121.     /* Pokud další index prvního volného prvku se rovná zároveň prvnímu prvku, je fronta plná */
  122.     /* Jde o to, že fronta se na posledním místě odkáže zpět na první místo */
  123.     return (nextIndex(q->b_index) == q->f_index) ? 1 : 0;
  124. }
  125.  
  126. void queueFront (const tQueue* q, char* c) {
  127. /*
  128. ** Prostřednictvím parametru c crátí znak ze začátku fronty q.
  129. ** Pokud je fronta prázdná, ošetřete to voláním funkce queueError(QERR_FRONT).
  130. ** Volání této funkce při prázdné frontě je vždy nutné považovat za nekorektní.
  131. ** Bývá to totiž důsledek špatného návrhu algoritmu, ve kterém je fronta
  132. ** použita. O takové situaci se proto musí programátor-vývojář dozvědět.
  133. ** V opačném případě je ladění programů obtížnější!
  134. **
  135. ** Při implementaci využijte dříve definované funkce queueEmpty.
  136. */
  137.     /* Pokud je fronta prázdná, vrátíme požadované chybové hlášení */
  138.     if (queueEmpty(q))
  139.         queueError(QERR_FRONT);
  140.     /* Vrátíme znak, který se nacházím na začátku fronty */
  141.     else
  142.         *c = q->arr[q->f_index];
  143. }
  144.  
  145. void queueRemove (tQueue* q) {
  146. /*
  147. ** Odstraní znak ze začátku fronty q. Pokud je fronta prázdná, ošetřete
  148. ** vzniklou chybu voláním funkce queueError(QERR_REMOVE).
  149. ** Hodnotu na uvolněné pozici ve frontě nijak neošetřujte (nepřepisujte).
  150. ** Při implementaci využijte dříve definované funkce queueEmpty a nextIndex.
  151. */
  152.  
  153.     /* Pokud je fronta prázdná, vrátíme požadované chybové hlášení */
  154.     if (queueEmpty(q))
  155.         queueError(QERR_REMOVE);
  156.     /* Odstraníme znak ze začátku fronty, ale tento znak nebude přímo odstraněnt, spíše se pouze posuneme */
  157.     else
  158.         q->f_index = nextIndex(q->f_index);
  159. }
  160.  
  161. void queueGet (tQueue* q, char* c) {
  162. /*
  163. ** Odstraní znak ze začátku fronty a vrátí ho prostřednictvím parametru c.
  164. ** Pokud je fronta prázdná, ošetřete to voláním funkce queueError(QERR_GET).
  165. **
  166. ** Při implementaci využijte dříve definovaných funkcí queueEmpty,
  167. ** queueFront a queueRemove.
  168. */
  169.     /* Pokud je fronta prázdná, vrátíme požadované chybové hlášení */
  170.     if (queueEmpty(q))
  171.         queueError(QERR_GET);
  172.     /* Vrátíme první znak z fronty do proměnné c a následně tento první znak vymažeme */
  173.     else
  174.     {
  175.         queueFront(q, c);
  176.         queueRemove(q);
  177.     }
  178. }
  179.  
  180. void queueUp (tQueue* q, char c) {
  181. /*
  182. ** Vloží znak c do fronty. Pokud je fronta plná, ošetřete chybu voláním
  183. ** funkce queueError(QERR_UP). Vkládání do plné fronty se považuje za
  184. ** nekorektní operaci. Situace by mohla být řešena i tak, že by operace
  185. ** neprováděla nic, ale v případě použití takto definované abstrakce by se
  186. ** obtížně odhalovaly chyby v algoritmech, které by abstrakci využívaly.
  187. **
  188. ** Při implementaci využijte dříve definovaných funkcí queueFull a nextIndex.
  189. */
  190.     /* Pokud je fronta plná, vrátíme požadované chybové hlášení */
  191.     if (queueFull(q))
  192.         queueError(QERR_UP);
  193.     /* Vložíme znak na první volné místo ve frontě a posuneme index volného místa o jeden dále */
  194.     else
  195.     {
  196.         q->arr[q->b_index] = c;
  197.         q->b_index = nextIndex(q->b_index);
  198.     }
  199. }
  200. /* Konec příkladu c203.c */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement