Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //queue.h
- /**
- * @author Victor Simonov
- * @version V1.0.5
- * @date 08/21/2016
- * @brief Implementing a queue based on a single-linked list
- * @detailed 2 queue types are supported. FIFO and LIFO.
- * For create queue just needs a user-defined structure with
- * "struct list_head *link" inside. Operations with structure elements occur
- * with qpush or qpop and qfree. Type of queue (FIFO/LIFO) set with queue_init.
- */
- /*
- * Create queue is simple operation that need just defined queue pointer and
- * init function.
- *
- * For example:
- * struct queue *longy = NULL; // not necessarily
- * queue_init(&longy, FIFO);
- *
- * For using queue need add a additional field in choosed structure of possible
- * stored elements. Queue allows store different types, but user must remeber
- * whitch type he use and witch order. If QUEUE_FORCE_SINGLE_TYPE was declared,
- * user can use shorter call of qpush and don't specify the type.
- *
- * For example:
- *
- * struct stored_elem struct stored_elem
- * { {
- * int a; ==> int a;
- * int b; ==> int b;
- * char c; ==> struct list_head *link;
- * short d; char c;
- * } short d;
- * }
- * struct stored_elem number1;
- *
- * Name of additional field is "link" and it is necessarily. The position
- * doesn't matter.
- * After that push and pop in queue becomes possible.
- *
- * For example:
- * qpush(longy, &number1, struct stored_elem);
- * or
- * #define QUEUE_FORCE_SINGLE_TYPE struct stored_elem
- * qpush(longy, &number1);
- *
- * For pop the element exists a qpop function with the same qpush manner.
- *
- * For example:
- * struct stored_elem return_value;
- * qpop(longly, &return_value, struct stored_elem);
- * or
- * #define QUEUE_FORCE_SINGLE_TYPE struct stored_elem
- * qpop(longly, &return_value);
- *
- * Deleting queue or free dynamic elements execute a qfree. It can free only
- * queue just links pointers set to NULL and free queue struct and free queue
- * with it elements.
- *
- * For example:
- * qfree(longly); // without elements freing
- * qfree(longly, struct stored_elem); // with elements
- */
- #ifndef __QUEUE_H_SINGLE_LIST__
- #define __QUEUE_H_SINGLE_LIST__
- #include <stdlib.h>
- #include <string.h>
- /**
- * @brief macro for error handling with zero number arg
- */
- #define dACTION_0() \
- __push()
- #define dACTION_1() \
- __pop()
- #define dACTION_2() \
- __free_()
- /**
- * @brief overloading macros
- * @detailed calculate number of args and call needed function
- */
- #define dFUNC_CHOOSER_3(_f1, _f2, _f3, N, ... ) N
- #define dFUNC_RECOMPOSER(argsWithParentheses) \
- dFUNC_CHOOSER_3 argsWithParentheses
- #define dMACRO_CHOOSER(target_, ...) \
- dCHOOSE_FROM_ARG_COUNT(target_, target_##_NO_ARG_EXPANDER __VA_ARGS__ ())
- #define dCHOOSE_FROM_ARG_COUNT(arg_, ...) \
- dFUNC_RECOMPOSER((__VA_ARGS__, arg_##_3, arg_##_2, arg_##_1, ))
- #define qpush_NO_ARG_EXPANDER() \
- ,,,dACTION_0
- #define qpop_NO_ARG_EXPANDER() \
- ,,,dACTION_1
- #define qfree_NO_ARG_EXPANDER() \
- ,,,dACTION_2
- #define qpush(...)\
- dMACRO_CHOOSER(qpush, __VA_ARGS__)(__VA_ARGS__)
- #define qpop(...)\
- dMACRO_CHOOSER(qpop, __VA_ARGS__)(__VA_ARGS__)
- #define qfree(...)\
- dMACRO_CHOOSER(qfree, __VA_ARGS__)(__VA_ARGS__)
- #define qisnempty(qptr) (unsigned char)(qptr->start != NULL)
- /**
- * @brief calculate strcucture element address by member address
- * @param[in] ptr member address
- * @param[in] type structure name
- * @param[in] member member name
- */
- #define list_entry(ptr, type, member) \
- ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
- /**
- * @brief calculate special member address by structure element address
- * @param[in] ptr member address
- * @param[in] type structure name
- * @param[in] member member name
- */
- #define entry_list(ptr, type, member) \
- ((struct list_head *)((char *)(ptr) + (unsigned long)(&((type *)0)->member)))
- /**
- * Various args macro overloading
- */
- #define qpush_3(queue, elem, type) \
- __push(queue, entry_list(elem, type, link))
- #define qpush_2(queue, elem) \
- __push(queue, (struct list_head *)&(elem->link))
- #define qpush_1(queue) \
- dACTION_0()
- #define qpop_3(queue, dptr, type) \
- __pop(queue, (void **)dptr, (unsigned long)(&((type *)0)->link))
- #define qpop_2(queue, dptr) \
- __pop(queue, (void **)dptr, \
- (unsigned long)(&((QUEUE_FORCE_SINGLE_TYPE *)0)->link))
- #define qpop_1(queue) \
- dACTION_1()
- #define qfree_2(queue, type) \
- __free_(queue, (unsigned long)(&((type *)0)->link))
- #define qfree_1(queue) \
- __free(queue)
- #define qfree_0(queue) \
- dACTION_2()
- typedef enum queue_type
- {
- FIFO = 0,
- LIFO
- } queue_type;
- /**
- * @brief structure-forming element
- */
- typedef struct list_head
- {
- struct list_head *next;
- } list_head;
- /**
- * @brief comfortable wrapper structure for queue
- */
- typedef struct queue
- {
- struct list_head *start;
- struct list_head *end; // don't used for LIFO
- enum queue_type type;
- unsigned long size_limit;
- unsigned long size;
- } queue;
- /**
- * @brief queue struct initialize
- * @papam[out] qptr queue pointer address
- * @papam[in] name queue type (FIFO/LIFO)
- *
- * @return 0 on success, 1 on parameter error and 2 on memory allocation error
- */
- static inline int queue_init(struct queue **qptr, enum queue_type name)
- {
- int rc = 0;
- if (qptr == NULL)
- {
- rc = 1;
- goto exit;
- }
- *qptr = (struct queue *)malloc(sizeof(struct queue));
- if (*qptr == NULL)
- {
- rc = 2;
- goto exit;
- }
- (*qptr)->start = NULL;
- (*qptr)->end = NULL;
- (*qptr)->type = name;
- (*qptr)->size = 0;
- memset(&(*qptr)->size_limit, 0xFF, sizeof(unsigned long));
- exit:
- return rc;
- }
- /**
- * @brief set queue size limit
- * @papam[out] qptr queue pointer address
- * @papam[in] queue size limit
- *
- * @return 0 on success, 1 on parameter error
- */
- static inline int qset_size_limit(struct queue *qptr, unsigned long limit)
- {
- int rc = 0;
- if (qptr == NULL)
- {
- rc = 1;
- goto exit;
- }
- qptr->size_limit = limit;
- exit:
- return rc;
- }
- /**
- * @brief change queue type (FIFO/LIFO)
- * @papam[in] qptr queue pointer address
- * @papam[in] name queue type (FIFO/LIFO)
- *
- * @return 0 on success, 1 on parameter error
- */
- static inline int qchange_type(struct queue *qptr, enum queue_type name)
- {
- int rc = 0;
- if (qptr == NULL)
- {
- rc = 1;
- goto exit;
- }
- qptr->type = name;
- exit:
- return rc;
- }
- /**
- * @brief add element in the queue
- * @papam[in] qptr queue pointer
- * @papam[in] lptr pointer to list head field in new element
- *
- * @return 0 on success, 1 for parameter error and 2 for overflow
- */
- static int __push(struct queue *qptr, struct list_head *lptr)
- {
- int rc = 0;
- if (qptr == NULL)
- {
- rc = 1;
- goto exit;
- }
- if (qptr->size >= qptr->size_limit)
- {
- rc = 2;
- goto exit;
- }
- if (qptr->type == FIFO)
- {
- if (lptr != NULL)
- {
- lptr->next = NULL;
- }
- if (qptr->end == NULL)
- {
- qptr->end = lptr;
- qptr->start = lptr;
- goto exit;
- }
- qptr->end->next = lptr;
- qptr->end = lptr;
- goto exit;
- }
- // LIFO
- if (lptr == NULL)
- {
- rc = 1;
- goto exit;
- }
- else
- {
- lptr->next = NULL;
- }
- if (qptr->start == NULL)
- {
- qptr->start = lptr;
- goto exit;
- }
- lptr->next = qptr->start;
- qptr->start = lptr;
- exit:
- if (rc == 0)
- {
- (qptr->size)++;
- }
- return rc;
- }
- /**
- * @brief extract element from queue
- * @papam[in] qptr queue pointer address
- * @papam[out] elem pointer to extracted element
- * @papam[in] offset (struct list_head *) field offset in the structure
- * @detailed for FIFO and LIFO is the same logic
- *
- * @return 0 on success, 1 for parameter error
- */
- static int __pop(
- struct queue *qptr
- , void **elem
- , unsigned long offset
- ){
- int rc = 0;
- struct list_head *temp = NULL;
- *elem = NULL;
- if (qptr == NULL)
- {
- rc = 1;
- goto exit;
- }
- if (elem == NULL)
- {
- rc = 1;
- goto exit;
- }
- if (qptr->start == NULL)
- {
- qptr->end = NULL;
- goto exit;
- }
- temp = qptr->start;
- qptr->start = qptr->start->next;
- *elem = (void *)((char *)temp - offset);
- temp->next = NULL;
- exit:
- if (rc == 0 && qptr->size != 0)
- {
- (qptr->size)--;
- }
- return rc;
- }
- /**
- * @brief recursive link destruct
- * @papam[in] lptr list_head pointer address
- */
- static inline void __free_head(struct list_head *lptr)
- {
- if (lptr != NULL)
- {
- if (lptr->next != NULL)
- {
- __free_head(lptr->next);
- lptr->next = NULL;
- }
- }
- }
- /**
- * @brief destruct queue and free queue structure
- * @papam[in] qptr queue pointer address
- * @detailed elements continue to exist
- */
- static void __free(struct queue *qptr)
- {
- __free_head(qptr->start);
- free(qptr);
- qptr = NULL;
- }
- /**
- * @brief destruct queue and free dynamic memory
- * @papam[in] qptr queue pointer address
- * @detailed this function needs to free queue elements
- */
- static void __free_(struct queue *qptr, unsigned int offset)
- {
- struct list_head *temp = NULL;
- while (qptr->start != NULL)
- {
- temp = qptr->start;
- qptr->start = qptr->start->next;
- free(temp - offset);
- }
- free(qptr);
- qptr = NULL;
- }
- #endif /* __QUEUE_H_SINGLE_LIST__ */
- /////////////////////////////////////////////////////////////
- //main.c
- #define _CRT_SECURE_NO_WARNINGS
- #include <stdlib.h>
- #include <stdio.h>
- #include <conio.h>
- #include <string.h>
- #include "queue.h"
- //macros
- #define MAX_NAME_LENGTH 512
- #define MAX_STR_LENGTH (MAX_NAME_LENGTH * 2 + 41)
- #define QUEUE_FORCE_SINGLE_TYPE struct timetable
- #define STORED_FORMAT "%u %s %s %lu %lu %u\n"
- typedef struct timetable
- {
- unsigned int ntrain;
- char *from;
- char *to;
- unsigned long from_time;
- unsigned long to_time;
- unsigned int cost;
- struct list_head *link;
- } timetable;
- struct queue *longy = NULL;
- /**
- * @brief stack show
- * @papam[in] qptr queue pointer address
- */
- static void show(queue * qptr);
- /**
- * @brief recursive link show
- * @papam[in] lptr list_head pointer address
- */
- static void __show_head(struct list_head *lptr);
- int main()
- {
- int rc = 0;
- FILE *db = NULL;
- char str[MAX_STR_LENGTH] = { 0 };
- char *estr = NULL;
- struct timetable *temp = NULL;
- char from[MAX_NAME_LENGTH] = { 0 };
- char to[MAX_NAME_LENGTH] = { 0 };
- unsigned char command = 0;
- queue_init(&longy, FIFO);
- db = fopen("timetable.db", "r");
- while (db != NULL)
- {
- if (feof(db) != 0)
- {
- break;
- }
- estr = fgets(str, sizeof(str), db);
- if (estr == NULL)
- {
- continue;
- }
- temp = (struct timetable *)malloc(sizeof(struct timetable));
- sscanf(str, STORED_FORMAT
- , &temp->ntrain
- , from
- , to
- , &temp->from_time
- , &temp->to_time
- , &temp->cost
- );
- temp->from = (char *)malloc(strlen(from) + 1);
- strcpy(temp->from, from);
- temp->to = (char *)malloc(strlen(to) + 1);
- strcpy(temp->to, to);
- qpush(longy, temp);
- }
- if (db != NULL)
- {
- fclose(db);
- }
- qchange_type(longy, LIFO);
- show(longy);
- while (1)
- {
- printf("\e[1G-- type 'a' to add, p to pop, e to exit --\n\e[1G");
- command = (unsigned char)_getch();
- if (command == 'e')
- {
- break;
- }
- if (command != 'a' && command != 'p')
- {
- continue;
- }
- if (command == 'p')
- {
- qpop(longy, &temp);
- if (temp != NULL)
- {
- free(temp->from);
- free(temp->to);
- free(temp);
- }
- show(longy);
- continue;
- }
- temp = (struct timetable *)malloc(sizeof(struct timetable));
- printf("\e[1Gnumber: ");
- scanf("%u", &temp->ntrain);
- printf("\e[1Gfrom: ");
- scanf("%s", from);
- temp->from = (char *)malloc(strlen(from) + 1);
- strcpy(temp->from, from);
- printf("\e[1Gto: ");
- scanf("%s", to);
- temp->to = (char *)malloc(strlen(to) + 1);
- strcpy(temp->to, to);
- printf("\e[1Gfrom_time: ");
- scanf("%lu", &temp->from_time);
- printf("\e[1Gto_time: ");
- scanf("%lu", &temp->to_time);
- printf("\e[1Gcost: ");
- scanf("%u", &temp->cost);
- qpush(longy, temp);
- show(longy);
- }
- qchange_type(longy, FIFO);
- db = fopen("timetable.db", "w");
- if (db == NULL)
- {
- rc = 1;
- goto exit;
- }
- while (1)
- {
- qpop(longy, &temp);
- if (temp == NULL)
- {
- break;
- }
- fprintf(db, STORED_FORMAT
- , temp->ntrain
- , temp->from
- , temp->to
- , temp->from_time
- , temp->to_time
- , temp->cost
- );
- free(temp->from);
- free(temp->to);
- free(temp);
- }
- exit:
- fclose(db);
- qfree(longy);
- return rc;
- }
- /**
- * @brief stack show
- * @papam[in] qptr queue pointer address
- */
- static void show(queue * qptr)
- {
- printf("\e[1GCurrent stack:\n");
- __show_head(qptr->start);
- }
- /**
- * @brief recursive link show
- * @papam[in] lptr list_head pointer address
- */
- static void __show_head(struct list_head *lptr)
- {
- struct timetable *temp = NULL;
- if (lptr == NULL)
- {
- return;
- }
- temp = list_entry(lptr, QUEUE_FORCE_SINGLE_TYPE, link);
- printf("\e[1G"STORED_FORMAT
- , temp->ntrain
- , temp->from
- , temp->to
- , temp->from_time
- , temp->to_time
- , temp->cost
- );
- __show_head(lptr->next);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement