Advertisement
Savelyev_Vyacheslav

7 lab C

Oct 28th, 2020 (edited)
240
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 13.76 KB | None | 0 0
  1. //queue.h
  2. /**
  3.  * @author Victor Simonov
  4.  * @version V1.0.5
  5.  * @date 08/21/2016
  6.  * @brief Implementing a queue based on a single-linked list
  7.  * @detailed 2 queue types are supported. FIFO and LIFO.
  8.  * For create queue just needs a user-defined structure with
  9.  * "struct list_head *link" inside. Operations with structure elements occur
  10.  * with qpush or qpop and qfree. Type of queue (FIFO/LIFO) set with queue_init.
  11.  */
  12.  
  13. /*
  14.  * Create queue is simple operation that need just defined queue pointer and
  15.  * init function.
  16.  *
  17.  * For example:
  18.  *     struct queue *longy = NULL; // not necessarily
  19.  *     queue_init(&longy, FIFO);
  20.  *
  21.  * For using queue need add a additional field in choosed structure of possible
  22.  * stored elements. Queue allows store different types, but user must remeber
  23.  * whitch type he use and witch order. If QUEUE_FORCE_SINGLE_TYPE was declared,
  24.  * user can use shorter call of qpush and don't specify the type.
  25.  *
  26.  * For example:
  27.  *
  28.  *     struct stored_elem           struct stored_elem
  29.  *     {                            {
  30.  *         int a;            ==>        int a;
  31.  *         int b;            ==>        int b;
  32.  *         char c;           ==>        struct list_head *link;
  33.  *         short d;                     char c;
  34.  *     }                                short d;
  35.  *                                  }
  36.  *     struct stored_elem number1;
  37.  *
  38.  * Name of additional field is "link" and it is necessarily. The position
  39.  * doesn't matter.
  40.  * After that push and pop in queue becomes possible.
  41.  *
  42.  * For example:
  43.  *     qpush(longy, &number1, struct stored_elem);
  44.  * or
  45.  *     #define QUEUE_FORCE_SINGLE_TYPE struct stored_elem
  46.  *     qpush(longy, &number1);
  47.  *
  48.  * For pop the element exists a qpop function with the same qpush manner.
  49.  *
  50.  * For example:
  51.  *     struct stored_elem return_value;
  52.  *     qpop(longly, &return_value, struct stored_elem);
  53.  * or
  54.  *     #define QUEUE_FORCE_SINGLE_TYPE struct stored_elem
  55.  *     qpop(longly, &return_value);
  56.  *
  57.  * Deleting queue or free dynamic elements execute a qfree. It can free only
  58.  * queue just links pointers set to NULL and free queue struct and free queue
  59.  * with it elements.
  60.  *
  61.  * For example:
  62.  *     qfree(longly);  // without elements freing
  63.  *     qfree(longly, struct stored_elem);  // with elements
  64.  */
  65.  
  66. #ifndef __QUEUE_H_SINGLE_LIST__
  67. #define __QUEUE_H_SINGLE_LIST__
  68.  
  69. #include <stdlib.h>
  70. #include <string.h>
  71.  
  72. /**
  73.  * @brief macro for error handling with zero number arg
  74.  */
  75. #define dACTION_0() \
  76.     __push()
  77.  
  78. #define dACTION_1() \
  79.     __pop()
  80.  
  81. #define dACTION_2() \
  82.     __free_()
  83.  
  84.  
  85. /**
  86.  * @brief overloading macros
  87.  * @detailed calculate number of args and call needed function
  88.  */
  89. #define dFUNC_CHOOSER_3(_f1, _f2, _f3, N, ... ) N
  90.  
  91. #define dFUNC_RECOMPOSER(argsWithParentheses) \
  92.     dFUNC_CHOOSER_3 argsWithParentheses
  93.  
  94. #define dMACRO_CHOOSER(target_, ...) \
  95.     dCHOOSE_FROM_ARG_COUNT(target_, target_##_NO_ARG_EXPANDER __VA_ARGS__ ())
  96.  
  97. #define dCHOOSE_FROM_ARG_COUNT(arg_, ...) \
  98.     dFUNC_RECOMPOSER((__VA_ARGS__, arg_##_3, arg_##_2, arg_##_1, ))
  99.  
  100. #define qpush_NO_ARG_EXPANDER() \
  101.     ,,,dACTION_0
  102.  
  103. #define qpop_NO_ARG_EXPANDER() \
  104.     ,,,dACTION_1
  105.  
  106. #define qfree_NO_ARG_EXPANDER() \
  107.     ,,,dACTION_2
  108.  
  109. #define qpush(...)\
  110.     dMACRO_CHOOSER(qpush, __VA_ARGS__)(__VA_ARGS__)
  111.  
  112. #define qpop(...)\
  113.     dMACRO_CHOOSER(qpop, __VA_ARGS__)(__VA_ARGS__)
  114.  
  115. #define qfree(...)\
  116.     dMACRO_CHOOSER(qfree, __VA_ARGS__)(__VA_ARGS__)
  117.  
  118. #define qisnempty(qptr) (unsigned char)(qptr->start != NULL)
  119.  
  120. /**
  121.  * @brief calculate strcucture element address by member address
  122.  * @param[in] ptr member address
  123.  * @param[in] type structure name
  124.  * @param[in] member member name
  125.  */
  126. #define list_entry(ptr, type, member) \
  127.     ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
  128.  
  129. /**
  130.  * @brief calculate special member address by structure element address
  131.  * @param[in] ptr member address
  132.  * @param[in] type structure name
  133.  * @param[in] member member name
  134.  */
  135. #define entry_list(ptr, type, member) \
  136.     ((struct list_head *)((char *)(ptr) + (unsigned long)(&((type *)0)->member)))
  137.  
  138. /**
  139.  * Various args macro overloading
  140.  */
  141. #define qpush_3(queue, elem, type) \
  142.     __push(queue, entry_list(elem, type, link))
  143.  
  144. #define qpush_2(queue, elem) \
  145.     __push(queue, (struct list_head *)&(elem->link))
  146.  
  147. #define qpush_1(queue) \
  148.     dACTION_0()
  149.  
  150. #define qpop_3(queue, dptr, type) \
  151.     __pop(queue, (void **)dptr, (unsigned long)(&((type *)0)->link))
  152.  
  153. #define qpop_2(queue, dptr) \
  154.     __pop(queue, (void **)dptr, \
  155.         (unsigned long)(&((QUEUE_FORCE_SINGLE_TYPE *)0)->link))
  156.  
  157. #define qpop_1(queue) \
  158.     dACTION_1()
  159.  
  160. #define qfree_2(queue, type) \
  161.     __free_(queue, (unsigned long)(&((type *)0)->link))
  162.  
  163. #define qfree_1(queue) \
  164.     __free(queue)
  165.  
  166. #define qfree_0(queue) \
  167.     dACTION_2()
  168.  
  169.  
  170. typedef enum queue_type
  171. {
  172.     FIFO = 0,
  173.     LIFO
  174. } queue_type;
  175.  
  176. /**
  177.  * @brief structure-forming element
  178.  */
  179. typedef struct list_head
  180. {
  181.     struct list_head *next;
  182. } list_head;
  183.  
  184. /**
  185.  * @brief comfortable wrapper structure for queue
  186.  */
  187. typedef struct queue
  188. {
  189.     struct list_head *start;
  190.     struct list_head *end;  // don't used for LIFO
  191.     enum queue_type type;
  192.     unsigned long size_limit;
  193.     unsigned long size;
  194. } queue;
  195.  
  196. /**
  197.  * @brief queue struct initialize
  198.  * @papam[out] qptr queue pointer address
  199.  * @papam[in] name queue type (FIFO/LIFO)
  200.  *
  201.  * @return 0 on success, 1 on parameter error and 2 on memory allocation error
  202.  */
  203. static inline int queue_init(struct queue **qptr, enum queue_type name)
  204. {
  205.     int rc = 0;
  206.  
  207.     if (qptr == NULL)
  208.     {
  209.         rc = 1;
  210.         goto exit;
  211.     }
  212.  
  213.     *qptr = (struct queue *)malloc(sizeof(struct queue));
  214.     if (*qptr == NULL)
  215.     {
  216.         rc = 2;
  217.         goto exit;
  218.     }
  219.  
  220.     (*qptr)->start = NULL;
  221.     (*qptr)->end = NULL;
  222.     (*qptr)->type = name;
  223.     (*qptr)->size = 0;
  224.     memset(&(*qptr)->size_limit, 0xFF, sizeof(unsigned long));
  225.  
  226. exit:
  227.     return rc;
  228. }
  229.  
  230. /**
  231.  * @brief set queue size limit
  232.  * @papam[out] qptr queue pointer address
  233.  * @papam[in] queue size limit
  234.  *
  235.  * @return 0 on success, 1 on parameter error
  236.  */
  237. static inline int qset_size_limit(struct queue *qptr, unsigned long limit)
  238. {
  239.     int rc = 0;
  240.  
  241.     if (qptr == NULL)
  242.     {
  243.         rc = 1;
  244.         goto exit;
  245.     }
  246.  
  247.     qptr->size_limit = limit;
  248.  
  249. exit:
  250.     return rc;
  251. }
  252.  
  253. /**
  254.  * @brief change queue type (FIFO/LIFO)
  255.  * @papam[in] qptr queue pointer address
  256.  * @papam[in] name queue type (FIFO/LIFO)
  257.  *
  258.  * @return 0 on success, 1 on parameter error
  259.  */
  260. static inline int qchange_type(struct queue *qptr, enum queue_type name)
  261. {
  262.     int rc = 0;
  263.  
  264.     if (qptr == NULL)
  265.     {
  266.         rc = 1;
  267.         goto exit;
  268.     }
  269.  
  270.     qptr->type = name;
  271.  
  272. exit:
  273.     return rc;
  274. }
  275.  
  276. /**
  277.  * @brief add element in the queue
  278.  * @papam[in] qptr queue pointer
  279.  * @papam[in] lptr pointer to list head field in new element
  280.  *
  281.  * @return 0 on success, 1 for parameter error and 2 for overflow
  282.  */
  283. static int __push(struct queue *qptr, struct list_head *lptr)
  284. {
  285.     int rc = 0;
  286.  
  287.     if (qptr == NULL)
  288.     {
  289.         rc = 1;
  290.         goto exit;
  291.     }
  292.  
  293.     if (qptr->size >= qptr->size_limit)
  294.     {
  295.         rc = 2;
  296.         goto exit;
  297.     }
  298.  
  299.     if (qptr->type == FIFO)
  300.     {
  301.         if (lptr != NULL)
  302.         {
  303.             lptr->next = NULL;
  304.         }
  305.         if (qptr->end == NULL)
  306.         {
  307.             qptr->end = lptr;
  308.             qptr->start = lptr;
  309.             goto exit;
  310.         }
  311.  
  312.         qptr->end->next = lptr;
  313.         qptr->end = lptr;
  314.         goto exit;
  315.     }
  316.  
  317.     // LIFO
  318.     if (lptr == NULL)
  319.     {
  320.         rc = 1;
  321.         goto exit;
  322.     }
  323.     else
  324.     {
  325.         lptr->next = NULL;
  326.     }
  327.  
  328.     if (qptr->start == NULL)
  329.     {
  330.         qptr->start = lptr;
  331.         goto exit;
  332.     }
  333.  
  334.     lptr->next = qptr->start;
  335.     qptr->start = lptr;
  336.  
  337. exit:
  338.     if (rc == 0)
  339.     {
  340.         (qptr->size)++;
  341.     }
  342.     return rc;
  343. }
  344.  
  345. /**
  346.  * @brief extract element from queue
  347.  * @papam[in] qptr queue pointer address
  348.  * @papam[out] elem pointer to extracted element
  349.  * @papam[in] offset (struct list_head *) field offset in the structure
  350.  * @detailed for FIFO and LIFO is the same logic
  351.  *
  352.  * @return 0 on success, 1 for parameter error
  353.  */
  354. static int __pop(
  355.     struct queue *qptr
  356.   , void **elem
  357.   , unsigned long offset
  358. ){
  359.     int rc = 0;
  360.     struct list_head *temp = NULL;
  361.  
  362.     *elem = NULL;
  363.  
  364.     if (qptr == NULL)
  365.     {
  366.         rc = 1;
  367.         goto exit;
  368.     }
  369.     if (elem == NULL)
  370.     {
  371.         rc = 1;
  372.         goto exit;
  373.     }
  374.  
  375.     if (qptr->start == NULL)
  376.     {
  377.         qptr->end = NULL;
  378.         goto exit;
  379.     }
  380.     temp = qptr->start;
  381.  
  382.     qptr->start = qptr->start->next;
  383.     *elem = (void *)((char *)temp - offset);
  384.     temp->next = NULL;
  385.  
  386. exit:
  387.     if (rc == 0 && qptr->size != 0)
  388.     {
  389.         (qptr->size)--;
  390.     }
  391.     return rc;
  392. }
  393.  
  394. /**
  395.  * @brief recursive link destruct
  396.  * @papam[in] lptr list_head pointer address
  397.  */
  398. static inline void __free_head(struct list_head *lptr)
  399. {
  400.     if (lptr != NULL)
  401.     {
  402.         if (lptr->next != NULL)
  403.         {
  404.             __free_head(lptr->next);
  405.             lptr->next = NULL;
  406.         }
  407.     }
  408. }
  409.  
  410.  
  411. /**
  412.  * @brief destruct queue and free queue structure
  413.  * @papam[in] qptr queue pointer address
  414.  * @detailed elements continue to exist
  415.  */
  416. static void __free(struct queue *qptr)
  417. {
  418.     __free_head(qptr->start);
  419.     free(qptr);
  420.     qptr = NULL;
  421. }
  422.  
  423. /**
  424.  * @brief destruct queue and free dynamic memory
  425.  * @papam[in] qptr queue pointer address
  426.  * @detailed this function needs to free queue elements
  427.  */
  428. static void __free_(struct queue *qptr, unsigned int offset)
  429. {
  430.     struct list_head *temp = NULL;
  431.  
  432.     while (qptr->start != NULL)
  433.     {
  434.         temp = qptr->start;
  435.         qptr->start = qptr->start->next;
  436.         free(temp - offset);
  437.     }
  438.  
  439.     free(qptr);
  440.     qptr = NULL;
  441. }
  442.  
  443.  
  444. #endif /* __QUEUE_H_SINGLE_LIST__ */
  445.  
  446.  
  447.  
  448.  
  449.  
  450. /////////////////////////////////////////////////////////////
  451.  
  452.  
  453.  
  454. //main.c
  455. #define _CRT_SECURE_NO_WARNINGS
  456.  
  457. #include <stdlib.h>
  458. #include <stdio.h>
  459. #include <conio.h>
  460. #include <string.h>
  461.  
  462. #include "queue.h"
  463. //macros
  464. #define MAX_NAME_LENGTH 512
  465. #define MAX_STR_LENGTH (MAX_NAME_LENGTH * 2 + 41)
  466. #define QUEUE_FORCE_SINGLE_TYPE struct timetable
  467. #define STORED_FORMAT "%u %s %s %lu %lu %u\n"
  468.  
  469. typedef struct timetable
  470. {
  471.     unsigned int ntrain;
  472.     char *from;
  473.     char *to;
  474.     unsigned long from_time;
  475.     unsigned long to_time;
  476.     unsigned int cost;
  477.     struct list_head *link;
  478. } timetable;
  479.  
  480. struct queue *longy = NULL;
  481.  
  482. /**
  483.  * @brief stack show
  484.  * @papam[in] qptr queue pointer address
  485.  */
  486. static void show(queue * qptr);
  487.  
  488. /**
  489.  * @brief recursive link show
  490.  * @papam[in] lptr list_head pointer address
  491.  */
  492. static void __show_head(struct list_head *lptr);
  493.  
  494. int main()
  495. {                              
  496.     int rc = 0;
  497.     FILE *db = NULL;
  498.     char str[MAX_STR_LENGTH] = { 0 };
  499.     char *estr = NULL;
  500.     struct timetable *temp = NULL;
  501.     char from[MAX_NAME_LENGTH] = { 0 };
  502.     char to[MAX_NAME_LENGTH] = { 0 };
  503.     unsigned char command = 0;
  504.  
  505.     queue_init(&longy, FIFO);
  506.  
  507.     db = fopen("timetable.db", "r");
  508.  
  509.     while (db != NULL)
  510.     {
  511.         if (feof(db) != 0)
  512.         {
  513.             break;
  514.         }
  515.         estr = fgets(str, sizeof(str), db);
  516.         if (estr == NULL)
  517.         {
  518.             continue;
  519.         }
  520.  
  521.         temp = (struct timetable *)malloc(sizeof(struct timetable));
  522.         sscanf(str, STORED_FORMAT
  523.             , &temp->ntrain
  524.             , from
  525.             , to
  526.             , &temp->from_time
  527.             , &temp->to_time
  528.             , &temp->cost
  529.         );
  530.         temp->from = (char *)malloc(strlen(from) + 1);
  531.         strcpy(temp->from, from);
  532.         temp->to = (char *)malloc(strlen(to) + 1);
  533.         strcpy(temp->to, to);
  534.         qpush(longy, temp);
  535.     }
  536.  
  537.     if (db != NULL)
  538.     {
  539.         fclose(db);
  540.     }
  541.  
  542.     qchange_type(longy, LIFO);
  543.     show(longy);
  544.  
  545.     while (1)
  546.     {
  547.         printf("\e[1G-- type 'a' to add, p to pop, e to exit --\n\e[1G");
  548.         command = (unsigned char)_getch();
  549.         if (command == 'e')
  550.         {
  551.             break;
  552.         }
  553.         if (command != 'a' && command != 'p')
  554.         {
  555.             continue;
  556.         }
  557.         if (command == 'p')
  558.         {
  559.             qpop(longy, &temp);
  560.             if (temp != NULL)
  561.             {
  562.                 free(temp->from);
  563.                 free(temp->to);
  564.                 free(temp);
  565.             }
  566.             show(longy);
  567.             continue;
  568.         }
  569.  
  570.         temp = (struct timetable *)malloc(sizeof(struct timetable));
  571.         printf("\e[1Gnumber: ");
  572.         scanf("%u", &temp->ntrain);
  573.         printf("\e[1Gfrom: ");
  574.         scanf("%s", from);
  575.         temp->from = (char *)malloc(strlen(from) + 1);
  576.         strcpy(temp->from, from);
  577.         printf("\e[1Gto: ");
  578.         scanf("%s", to);
  579.         temp->to = (char *)malloc(strlen(to) + 1);
  580.         strcpy(temp->to, to);
  581.         printf("\e[1Gfrom_time: ");
  582.         scanf("%lu", &temp->from_time);
  583.         printf("\e[1Gto_time: ");
  584.         scanf("%lu", &temp->to_time);
  585.         printf("\e[1Gcost: ");
  586.         scanf("%u", &temp->cost);
  587.         qpush(longy, temp);
  588.         show(longy);
  589.     }
  590.  
  591.     qchange_type(longy, FIFO);
  592.  
  593.     db = fopen("timetable.db", "w");
  594.     if (db == NULL)
  595.     {
  596.         rc = 1;
  597.         goto exit;
  598.     }
  599.  
  600.     while (1)
  601.     {
  602.         qpop(longy, &temp);
  603.         if (temp == NULL)
  604.         {
  605.             break;
  606.         }
  607.         fprintf(db, STORED_FORMAT
  608.             , temp->ntrain
  609.             , temp->from
  610.             , temp->to
  611.             , temp->from_time
  612.             , temp->to_time
  613.             , temp->cost
  614.         );
  615.         free(temp->from);
  616.         free(temp->to);
  617.         free(temp);
  618.     }
  619.  
  620. exit:
  621.     fclose(db);
  622.     qfree(longy);
  623.     return rc;
  624. }
  625.  
  626. /**
  627.  * @brief stack show
  628.  * @papam[in] qptr queue pointer address
  629.  */
  630. static void show(queue * qptr)
  631. {
  632.     printf("\e[1GCurrent stack:\n");
  633.     __show_head(qptr->start);
  634. }
  635.  
  636.  
  637. /**
  638.  * @brief recursive link show
  639.  * @papam[in] lptr list_head pointer address
  640.  */
  641. static void __show_head(struct list_head *lptr)
  642. {
  643.     struct timetable *temp = NULL;
  644.  
  645.     if (lptr == NULL)
  646.     {
  647.         return;
  648.     }
  649.  
  650.     temp = list_entry(lptr, QUEUE_FORCE_SINGLE_TYPE, link);
  651.  
  652.     printf("\e[1G"STORED_FORMAT
  653.         , temp->ntrain
  654.         , temp->from
  655.         , temp->to
  656.         , temp->from_time
  657.         , temp->to_time
  658.         , temp->cost
  659.     );
  660.  
  661.     __show_head(lptr->next);
  662. }
  663.  
  664.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement