// калькулятор на основе обратной польской записи // gcc stack_test.c stack.c -o stack_test.exe #include "stack.h" #include #include #include // Тестирование сценария: // Токен: 2 -> Стек: [2] // Токен: 2 -> Стек: [2, 2] // Токен: 10 -> Стек: [2, 2, 10] // Токен: 3 -> Стек: [2, 2, 10, 3] // Токен: - -> Берем 3 и 10: 10-3=7 -> Стек: [2, 2, 7] // Токен: * -> Берем 7 и 2: 2*7=14 -> Стек: [2, 14] // Токен: x -> Стек: [2, 14, x] // Токен: 8 -> Стек: [2, 14, x, 8] // Токен: - -> Берем 8 и x: x-8 -> Стек: [2, 14, (x-8)] // Токен: * -> Берем (x-8) и 14: 14*(x-8) -> Стек: [2, (14*(x-8))] // Токен: + -> Берем (14*(x-8)) и 2: 2+(14*(x-8)) -> Стек: [(2+(14*(x-8)))] // Ответ: (2+(14*(x-8))) // P.S. и еще нескольких char* calulate(Element* tokens, int tokens_count) { #define MAX_ELEMENT_STRING_SIZE 100 Stack s_operands; initStack(&s_operands); for (int i = 0; i < tokens_count; ++i) { Element token = tokens[i]; if (token.type == 'n' || token.type == 'v') { // если число или выражение с переменной - добавляю в стек push(&s_operands, token.str_ptr, token.type); } else { // если оператор char op = token.str_ptr[0]; // беру со стека 2 последних операнда Element second_operand; pop(&s_operands, &second_operand); Element first_operand; pop(&s_operands, &first_operand); char result[MAX_ELEMENT_STRING_SIZE] = { 0 }; if (first_operand.type == 'n' && second_operand.type == 'n') { // оба операнда - числа => вычисляю значение выражения и его закидываю в стек int first_num = atoi(first_operand.str_ptr); int second_num = atoi(second_operand.str_ptr); switch (op) { case '+': { int result_num = first_num + second_num; //printf("%i + %i = %i\n", first_num, second_num, result_num); snprintf(result, MAX_ELEMENT_STRING_SIZE, "%d", result_num); push(&s_operands, result, 'n'); break; } case '-': { int result_num = first_num - second_num; //printf("%i - %i = %i\n", first_num, second_num, result_num); snprintf(result, MAX_ELEMENT_STRING_SIZE, "%d", result_num); push(&s_operands, result, 'n'); break; } case '*': { int result_num = first_num * second_num; //printf("%i * %i = %i\n", first_num, second_num, result_num); snprintf(result, MAX_ELEMENT_STRING_SIZE, "%d", result_num); push(&s_operands, result, 'n'); break; } } } else { // хотя бы один операнд содержит переменную snprintf(result, MAX_ELEMENT_STRING_SIZE, "(%s%c%s)", first_operand.str_ptr, op, second_operand.str_ptr); //printf("%s %c %s = %s\n", first_operand.str_ptr, op, second_operand.str_ptr, result); push(&s_operands, result, 'v'); // Помечаю как выражение с переменной } free(first_operand.str_ptr); free(second_operand.str_ptr); } } if (!isEmpty(&s_operands)) { Element result; pop(&s_operands, &result); //printf("Result: %s\n", result.str_ptr); return result.str_ptr; } return NULL; } int main() { char* res; Element tokens[100]; tokens[0].str_ptr = "2"; tokens[0].type = 'n'; // number tokens[1].str_ptr = "2"; tokens[1].type = 'n'; // number tokens[2].str_ptr = "10"; tokens[2].type = 'n'; // number tokens[3].str_ptr = "3"; tokens[3].type = 'n'; // number tokens[4].str_ptr = "-"; tokens[4].type = 'o'; // operator tokens[5].str_ptr = "*"; tokens[5].type = 'o'; // operator tokens[6].str_ptr = "x"; tokens[6].type = 'v'; // variable tokens[7].str_ptr = "8"; tokens[7].type = 'n'; // number tokens[8].str_ptr = "-"; tokens[8].type = 'o'; // operator tokens[9].str_ptr = "*"; tokens[9].type = 'o'; // operator tokens[10].str_ptr = "+"; tokens[10].type = 'o'; // operator res = calulate(tokens, 11); printf("Result: %s\n", res); free(res); tokens[0].str_ptr = "2"; tokens[0].type = 'n'; tokens[1].str_ptr = "2"; tokens[1].type = 'n'; tokens[2].str_ptr = "+"; tokens[2].type = 'o'; res = calulate(tokens, 3); printf("Result: %s\n", res); free(res); tokens[0].str_ptr = "2"; tokens[0].type = 'n'; tokens[1].str_ptr = "2"; tokens[1].type = 'n'; tokens[2].str_ptr = "+"; tokens[2].type = 'o'; tokens[3].str_ptr = "x"; tokens[3].type = 'v'; tokens[4].str_ptr = "*"; tokens[4].type = 'o'; res = calulate(tokens, 5); printf("Result: %s\n", res); free(res); return 0; }