diff --git a/semester_1/homework5/sortingStation/CMakeLists.txt b/semester_1/homework5/sortingStation/CMakeLists.txt new file mode 100644 index 0000000..8c0c6c7 --- /dev/null +++ b/semester_1/homework5/sortingStation/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.8.0) +project(sortingStation VERSION 0.1.0 LANGUAGES C) + +include(CTest) +enable_testing() + +add_executable(sortingStation main.c +sortingStation/sortingStation.c +Stack/Stack.c +getString/getString.c +tests/test.c +) + +set(CPACK_PROJECT_NAME ${PROJECT_NAME}) +set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) +include(CPack) diff --git a/semester_1/homework5/sortingStation/Stack/Stack.c b/semester_1/homework5/sortingStation/Stack/Stack.c new file mode 100644 index 0000000..a318291 --- /dev/null +++ b/semester_1/homework5/sortingStation/Stack/Stack.c @@ -0,0 +1,107 @@ +#include + +#include "Stack.h" + +typedef struct Node +{ + struct Node *next; + char value; +} Node; + +typedef struct Stack +{ + size_t length; + Node *head; +} Stack; + +Stack *createStack(void) +{ + return calloc(1, sizeof(Stack)); +} + +void deleteStack(Stack **const stack) +{ + Node *currentNode = (*stack)->head; + while (currentNode != NULL) + { + Node *temp = currentNode; + currentNode = currentNode->next; + free(temp); + } + free(*stack); + *stack = NULL; +} + +StackErrorCode addElement(Stack *const stack, const char value) +{ + Node *newNode = calloc(1, sizeof(Node)); + if (newNode == NULL) + { + return memoryErrorStack; + } + newNode->value = value; + if (stack->head != NULL) + { + newNode->next = stack->head; + } + stack->head = newNode; + ++(stack->length); + + return okStack; +} + +char getElement(Stack *const stack, StackErrorCode *const errorCode) +{ + if (stack->head == NULL) + { + *errorCode = emptyStack; + return 0; + } + + Node *temp = stack->head; + stack->head = temp->next; + char value = temp->value; + free(temp); + --(stack->length); + *errorCode = okStack; + return value; +} + +char topElement(Stack const *const stack, StackErrorCode *const errorCode) +{ + if (stack->head == NULL) + { + *errorCode = emptyStack; + return '\0'; + } + *errorCode = okStack; + return stack->head->value; +} + +char *createString(Stack const *const stack, StackErrorCode *const errorCode) +{ + if (stack == NULL || stack->head == NULL) + { + *errorCode = emptyStack; + return NULL; + } + + size_t strl = stack->length * 2; + char *output = (char *)malloc(strl * sizeof(char)); + if (output == NULL) + { + *errorCode = memoryErrorStack; + return NULL; + } + + size_t i = strl - 1; + for (Node *currentNode = stack->head; currentNode != NULL; currentNode = currentNode->next) + { + output[i - 1] = currentNode->value; + output[i] = ' '; + i -= 2; + } + + output[strl - 1] = '\0'; + return output; +} diff --git a/semester_1/homework5/sortingStation/Stack/Stack.h b/semester_1/homework5/sortingStation/Stack/Stack.h new file mode 100644 index 0000000..b819d71 --- /dev/null +++ b/semester_1/homework5/sortingStation/Stack/Stack.h @@ -0,0 +1,27 @@ +#pragma once + +typedef struct Stack Stack; +typedef enum StackErrorCode +{ + okStack, + memoryErrorStack, + emptyStack +} StackErrorCode; + +// создать пустой стек +Stack *createStack(void); + +// удалить стек +void deleteStack(Stack ** const stack); + +// добавить элемент в стек +StackErrorCode addElement(Stack *const stack, const char value); + +// взять верхний элемент из стека +char getElement(Stack *const stack, StackErrorCode * const errorCode); + +// получить значение верхней ячейки стека, не удаляя ее +char topElement(Stack const *const stack, StackErrorCode *const errorCode); + +// получить строку со всеми значениями стека, где самый правый элемент - самый верхний элемент стека +char *createString(Stack const *const stack, StackErrorCode * const errorCode); diff --git a/semester_1/homework5/sortingStation/getString/getString.c b/semester_1/homework5/sortingStation/getString/getString.c new file mode 100644 index 0000000..3f7a54f --- /dev/null +++ b/semester_1/homework5/sortingStation/getString/getString.c @@ -0,0 +1,37 @@ +#include +#include +#include + +#include "getString.h" + +char *getString(FILE const * const file, char const endOfLine) +{ + size_t len = 0; + size_t capacity = 1; + char *s = (char *)malloc(sizeof(char)); + if (s == NULL) + { + return NULL; + } + + for (char c = fgetc(file); c != endOfLine && c != EOF; c = fgetc(file)) + { + s[len++] = c; + + if (len >= capacity) + { + capacity *= 2; + char *tmp = (char *)realloc(s, capacity * sizeof(char)); + if (tmp == NULL) + { + free(s); + return NULL; + } + s = tmp; + } + } + + s[len] = '\0'; + + return s; +} diff --git a/semester_1/homework5/sortingStation/getString/getString.h b/semester_1/homework5/sortingStation/getString/getString.h new file mode 100644 index 0000000..6f21e6f --- /dev/null +++ b/semester_1/homework5/sortingStation/getString/getString.h @@ -0,0 +1,8 @@ +#pragma once + +#include +#include +#include + +// получить строку из *file до разделителя endOfLine +char *getString(FILE const * const file, char const endOfLine); diff --git a/semester_1/homework5/sortingStation/main.c b/semester_1/homework5/sortingStation/main.c new file mode 100644 index 0000000..b5e4910 --- /dev/null +++ b/semester_1/homework5/sortingStation/main.c @@ -0,0 +1,47 @@ +#include +#include +#include + +#include "sortingStation/sortingStation.h" +#include "getString/getString.h" +#include "tests/test.h" + +typedef enum ExitCode +{ + programFinishedCorrectly, + programFailedTests, + memoryError + +} ExitCode; + +int main(void) +{ + setlocale(LC_ALL, "Russian"); + + if (test()) + { + printf("К сожалению, программа сейчас не работает\n"); + return programFailedTests; + } + + printf("Введите арифметическое выражение в инфиксной форме: "); + char * expression = getString(stdin, '\n'); + if (expression == NULL) + { + printf("\nНедостаточно памяти\n"); + return memoryError; + } + + printf("\nВыражение в постфиксной форме: "); + char * ex = createPostfixForm(expression); + free(expression); + if (ex == NULL) + { + printf("\nНедостаточно памяти\n"); + return memoryError; + } + + printf("%s\n", ex); + free(ex); + return programFinishedCorrectly; +} diff --git a/semester_1/homework5/sortingStation/sortingStation/sortingStation.c b/semester_1/homework5/sortingStation/sortingStation/sortingStation.c new file mode 100644 index 0000000..87a85a7 --- /dev/null +++ b/semester_1/homework5/sortingStation/sortingStation/sortingStation.c @@ -0,0 +1,119 @@ +#include +#include +#include + +#include "../Stack/Stack.h" +#include "sortingStation.h" + +static void ignoreSpaces(char const *const expression, size_t *const counter) +{ + for (; expression[*counter] == ' '; ++(*counter)) + ; +} + +static int compareOperators(char const operator1, char const operator2) +{ + if (operator1 == '*' || operator1 == '/') + { + if (operator2 == '+' || operator2 == '-') + { + return 1; + } + return 0; + } + else + { + if (operator2 == '+' || operator2 == '-') + { + return 0; + } + return -1; + } +} + +static StackErrorCode moveToOutputStack(Stack *const outputStack, Stack *const operatorsStack) +{ + StackErrorCode ec = okStack; + for (char currentOperator = getElement(operatorsStack, &ec); + currentOperator != '(' && ec != emptyStack; currentOperator = getElement(operatorsStack, &ec)) + { + StackErrorCode ec2 = addElement(outputStack, currentOperator); + if (ec2 != okStack) + { + return ec2; + } + } + return okStack; +} + +char *createPostfixForm(char const *const infixForm) +{ + size_t len = strlen(infixForm); + size_t counter = 0; + + Stack *outputStack = createStack(); + if (outputStack == NULL) + { + return NULL; + } + Stack *operatorsStack = createStack(); + if (operatorsStack == NULL) + { + deleteStack(&outputStack); + return NULL; + } + + StackErrorCode ec = okStack; + + for (size_t i = 0; i < len; ++i) + { + ignoreSpaces(infixForm, &i); + if (i >= len) + { + break; + } + char currentChar = infixForm[i]; + if (isdigit(currentChar)) + { + ec = addElement(outputStack, infixForm[i]); + } + else if (currentChar == ')') + { + ec = moveToOutputStack(outputStack, operatorsStack); + } + else if (currentChar == '(') + { + ec = addElement(operatorsStack, currentChar); + } + else + { + char top = topElement(operatorsStack, &ec); + int comparison = compareOperators(top, currentChar); + while (ec != emptyStack && top != '(' && comparison != -1) + { + char operatorFromStack = getElement(operatorsStack, &ec); + ec = addElement(outputStack, operatorFromStack); + if (ec != okStack) + { + deleteStack(&operatorsStack); + deleteStack(&outputStack); + return NULL; + } + top = topElement(operatorsStack, &ec); + comparison = compareOperators(top, currentChar); + } + ec = addElement(operatorsStack, currentChar); + } + if (ec != okStack) + { + deleteStack(&operatorsStack); + deleteStack(&outputStack); + return NULL; + } + } + ec = moveToOutputStack(outputStack, operatorsStack); + char *output = createString(outputStack, &ec); + deleteStack(&operatorsStack); + deleteStack(&outputStack); + return output; +} diff --git a/semester_1/homework5/sortingStation/sortingStation/sortingStation.h b/semester_1/homework5/sortingStation/sortingStation/sortingStation.h new file mode 100644 index 0000000..fa3f391 --- /dev/null +++ b/semester_1/homework5/sortingStation/sortingStation/sortingStation.h @@ -0,0 +1,4 @@ +#pragma once + +// получает на вход арифметическое выражение в инфиксной форме, возвращает то же выражение в постфиксной форме +char *createPostfixForm(char const *const infixForm); diff --git a/semester_1/homework5/sortingStation/tests/test.c b/semester_1/homework5/sortingStation/tests/test.c new file mode 100644 index 0000000..1fdd284 --- /dev/null +++ b/semester_1/homework5/sortingStation/tests/test.c @@ -0,0 +1,42 @@ +#include +#include + +#include "test.h" +#include "../sortingStation/sortingStation.h" + +const bool test(void) +{ + const size_t testNumber = 6; + const char * const testExpressions[testNumber] = { + "1 + 2", + " ( 2 + 4) * 5", + " 2 + 4 * 5 ", + " 4 * 6 * 7 * 8", + "(1 + (2 - 3) + (7 / 2)) * (1 + 8)", + "1" + }; + + const char * const answers[testNumber] = { + "1 2 +", + "2 4 + 5 *", + "2 4 5 * +", + "4 6 * 7 * 8 *", + "1 2 3 - 7 2 / + 1 8 + 8" + }; + + for (size_t i = 0; i < testNumber; ++i) + { + char * expression = createPostfixForm(testExpressions[i]); + if (expression == NULL) + { + return false; + } + int comparison = strcmp(expression, answers[i]); + free(expression); + if (comparison != 0) + { + return false; + } + } + return true; +} diff --git a/semester_1/homework5/sortingStation/tests/test.h b/semester_1/homework5/sortingStation/tests/test.h new file mode 100644 index 0000000..0e483cd --- /dev/null +++ b/semester_1/homework5/sortingStation/tests/test.h @@ -0,0 +1,6 @@ +#pragma once +#include + + +// тесты для функции char *createPostfixForm(char const *const infixForm) +const bool test(void);