diff --git a/HW4/ShuntingYard/src/main.c b/HW4/ShuntingYard/src/main.c new file mode 100644 index 0000000..5b66dcd --- /dev/null +++ b/HW4/ShuntingYard/src/main.c @@ -0,0 +1,130 @@ +#include "../../modules/queue/queue.h" +#include "../../modules/stack/stack.h" +#include +#include + +void shuntingYard(const char *expression); +int getPrecedence(char operation); + +int main() { + shuntingYard("1 + 1"); + shuntingYard("(1 + 1) * 2"); + shuntingYard("1 + 1 * 2"); + shuntingYard("3 + 4 * 2 / (1 - 5)"); + shuntingYard("1 + 2 + (3 + 4)"); + return 0; +} + +void shuntingYard(const char *expression) { + Stack *stackHead = NULL; + Queue *queueHead = NULL; + Queue *queueTail = NULL; + int errorCode = 0; + + for (int i = 0; expression[i] != '\0'; ++i) { + char currChar = expression[i]; + + if (isdigit(currChar)) { + errorCode = pushToQueue(currChar, &queueHead, &queueTail); + if (errorCode == -1) { + printf("Error: couldn't allocate memory\n"); + freeQueue(queueHead); + freeStack(stackHead); + return; + } + } else if (currChar == '+' || currChar == '-' || currChar == '*' || + currChar == '/') { + while (stackHead != NULL && + getPrecedence(currChar) <= getPrecedence(stackHead->data)) { + char lastStackOp = popFromStack(&stackHead); + if (lastStackOp == '\0') { + printf("Error: trying to put empty operation into queue\n"); + freeQueue(queueHead); + freeStack(stackHead); + return; + } + errorCode = pushToQueue(lastStackOp, &queueHead, &queueTail); + if (errorCode == -1) { + printf("Error: couldn't allocate memory\n"); + freeQueue(queueHead); + freeStack(stackHead); + return; + } + } + errorCode = pushToStack(currChar, &stackHead); + if (errorCode == -1) { + printf("Error: couldn't allocate memory\n"); + freeQueue(queueHead); + freeStack(stackHead); + return; + } + } else if (currChar == '(') { + errorCode = pushToStack(currChar, &stackHead); + if (errorCode == -1) { + printf("Error: couldn't allocate memory\n"); + freeQueue(queueHead); + freeStack(stackHead); + return; + } + } else if (currChar == ')') { + while (stackHead != NULL && stackHead->data != '(') { + char lastStackOp = popFromStack(&stackHead); + if (lastStackOp == '\0') { + printf("Error: trying to put empty operation into queue\n"); + freeQueue(queueHead); + freeStack(stackHead); + return; + } + errorCode = pushToQueue(lastStackOp, &queueHead, &queueTail); + if (errorCode == -1) { + printf("Error: couldn't allocate memory\n"); + freeQueue(queueHead); + freeStack(stackHead); + return; + } + } + if (popFromStack(&stackHead) != '(') { + printf("Error: mismatched parentheses\n"); + freeQueue(queueHead); + freeStack(stackHead); + return; + } + } else if (currChar != ' ') { + printf("Error: wrong math expression\n"); + freeQueue(queueHead); + freeStack(stackHead); + return; + } + } + while (stackHead != NULL) { + char lastStackOp = popFromStack(&stackHead); + if (lastStackOp == '\0') { + printf("Error: trying to put empty operation into queue\n"); + freeQueue(queueHead); + freeStack(stackHead); + return; + } + errorCode = pushToQueue(lastStackOp, &queueHead, &queueTail); + if (errorCode == -1) { + printf("Error: couldn't allocate memory\n"); + freeQueue(queueHead); + freeStack(stackHead); + return; + } + } + + printQueue(queueHead); + freeQueue(queueHead); + freeStack(stackHead); + return; +} + +int getPrecedence(char operation) { + if (operation == '/' || operation == '*') + return 1; + else if (operation == '-' || operation == '+') + return 0; + else + return -1; +} + diff --git a/HW4/modules/queue/queue.c b/HW4/modules/queue/queue.c new file mode 100644 index 0000000..f1603aa --- /dev/null +++ b/HW4/modules/queue/queue.c @@ -0,0 +1,39 @@ +#include "queue.h" +#include +#include + +int pushToQueue(char data, Queue **head, Queue **tail) { + Queue *newQueueNode = (Queue *)malloc(sizeof(Queue)); + if (newQueueNode == NULL) + return -1; + + newQueueNode->data = data; + newQueueNode->next = NULL; + + if (*head == NULL) { + *head = newQueueNode; + *tail = newQueueNode; + } else { + (*tail)->next = newQueueNode; + *tail = newQueueNode; + } + return 0; +} + +void printQueue(Queue *head) { + while (head != NULL) { + printf("%c ", head->data); + head = head->next; + } + printf("\n"); +} + +void freeQueue(Queue *head) { + Queue *current = head; + while (current != NULL) { + Queue *next = current->next; + free(current); + current = next; + } +} + diff --git a/HW4/modules/queue/queue.h b/HW4/modules/queue/queue.h new file mode 100644 index 0000000..b63f5e2 --- /dev/null +++ b/HW4/modules/queue/queue.h @@ -0,0 +1,28 @@ +#pragma once + +typedef struct Queue { + char data; + struct Queue *next; +} Queue; + +/** + * @brief Push element to queue + * @param data Character to push + * @param head Pointer to pointer of queue head + * @param tail Pointer to pointer of queue tail + * @return -1 if couldn't allocate memory, 0 otherwise + */ +int pushToQueue(char data, Queue **head, Queue **tail); + +/** + * @brief Print all elements in queue + * @param head Pointer to queue head + */ +void printQueue(Queue *head); + +/** + * @brief Free all queue memory + * @param head Pointer to queue head + */ +void freeQueue(Queue *head); + diff --git a/HW4/modules/stack/stack.c b/HW4/modules/stack/stack.c new file mode 100644 index 0000000..ac95e12 --- /dev/null +++ b/HW4/modules/stack/stack.c @@ -0,0 +1,37 @@ +#include "stack.h" +#include +#include + +int pushToStack(char data, Stack **head) { + Stack *newNode = + (Stack *)malloc(sizeof(Stack)); + if (newNode == NULL) + return -1; + else { + newNode->data = data; + newNode->next = *head; + *head = newNode; + return 0; + } +} + +char popFromStack(Stack **head) { + if (*head == NULL) + return '\0'; + + Stack *lastNode = *head; + char lastNodeData = lastNode->data; + *head = (*head)->next; + free(lastNode); + return lastNodeData; +} + +void freeStack(Stack *head) { + Stack *current = head; + while (current != NULL) { + Stack *next = current->next; + free(current); + current = next; + } +} + diff --git a/HW4/modules/stack/stack.h b/HW4/modules/stack/stack.h new file mode 100644 index 0000000..516ce3c --- /dev/null +++ b/HW4/modules/stack/stack.h @@ -0,0 +1,28 @@ +#pragma once + +typedef struct Stack { + char data; + struct Stack *next; +} Stack; + +/** + * @brief Push element to stack + * @param data Character to push + * @param head Pointer to pointer of stack head + * @return -1 if couldn't allocate memory, 0 otherwise + */ +int pushToStack(char data, Stack **head); + +/** + * @brief Pop element from stack + * @param head Pointer to pointer of stack head + * @return Popped character or '\0' if stack is empty + */ +char popFromStack(Stack **head); + +/** + * @brief Free all stack memory + * @param head Pointer to stack head + */ +void freeStack(Stack *head); +