Простейший инженерный калькулятор на основе алгоритма сортировочной станции
Пишу тривиальный инженерный калькулятор на основе алгоритма сортировочной станции. Всё в принципе работает.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <locale.h>
#include <wchar.h>
#define MAX_SIZE 100
typedef struct {
float data[MAX_SIZE]; // Данные стека
int top;// Вершина
} Stack;
void initialize(Stack* stack) {
stack->top = NULL;
}
int isEmpty(Stack* stack) {
return (stack->top == NULL);
}
void push(Stack* stack, float ch) {
if (stack->top == MAX_SIZE - 1) {
printf("Stack is overflowed\n");
return;
}
stack->data[++(stack->top)] = ch;
}
float pop(Stack* stack) {
if (isEmpty(stack)) {
printf("Stack is empty\n");
return '\0';
}
return stack->data[(stack->top)--];
}
int isOperator(char ch) {
return (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '^' || ch == '!' || ch == 'q' || ch == 's' || ch == 'c');
}
int getPriority(char ch) {
if (ch == '+' || ch == '-')
return 1;
else if (ch == '*' || ch == '/')
return 2;
else if (ch == '^' || ch == '!' || ch == 'q' || ch == 's' || ch == 'c')
return 3;
else
return 0;
}
void infixToPostfix(char* infix, char* postfix) {
Stack stack;
initialize(&stack);
int i, j;
int k = 0;
char ch;
char tmp[10];
char xs[123] = { 0 };
char xs1[123][10];
for (i = 0, j = 0; infix[i] != '\0'; i++) {
ch = infix[i];
if ((int)ch >= 97 && (int)ch <= 122 && ch != 'q' && ch != 's' && ch != 'c') {
if (xs[ch] > 0) {
while (isdigit(xs1[ch][k])) {
postfix[j++] = xs1[ch][k++];
}
k = 0;
postfix[j++] = ' ';
}
else {
printf("Enter the value of the symbol %c: ", ch);
fgets(tmp, 10,stdin);
while (isdigit(tmp[k])) {
postfix[j++] = tmp[k++];
}
k = 0;
postfix[j++] = ' ';
xs[ch]++;
while (isdigit(tmp[k])) {
xs1[(int)ch][k++] = tmp[k++];
}
k = 0;
}
}
if (ch == ' ' || ch == '\t')
continue;
if (isdigit(ch)) {
while (isdigit(infix[i])) {
postfix[j++] = infix[i++];
}
postfix[j++] = ' ';
i--;
}
else if (isOperator(ch)) {
while (!isEmpty(&stack) && getPriority(stack.data[stack.top]) >= getPriority(ch)) {
postfix[j++] = pop(&stack);
postfix[j++] = ' ';
}
push(&stack, ch);
}
else if (ch == '(') {
push(&stack, ch);
}
else if (ch == ')') {
while (!isEmpty(&stack) && stack.data[stack.top] != '(') {
postfix[j++] = pop(&stack);
postfix[j++] = ' ';
}
if (!isEmpty(&stack) && stack.data[stack.top] == '(') {
pop(&stack);
}
else {
printf("Error: wrong expression\n");
return;
}
}
}
while (!isEmpty(&stack)) {
if (stack.data[stack.top] == '(') {
printf("Error: wrong expression\n");
return;
}
postfix[j++] = pop(&stack);
postfix[j++] = ' ';
}
postfix[j] = '\0';
}
float evaluatePostfix(char* postfix) {
Stack stack;
initialize(&stack);
int i;
float result, operand1, operand2;
char num[10];
int numIndex = 0;
char ch;
for (i = 0; postfix[i] != '\0'; i++) {
ch = postfix[i];
if (isdigit(ch)) {
while (isdigit(postfix[i])) {
num[numIndex++] = postfix[i++];
}
num[numIndex] = '\0';
numIndex = 0;
push(&stack, atoi(num));
}
else if (ch == ' ') {
continue;
}
else if (isOperator(ch)) {
if (ch == '!' || ch == 'q' || ch == 's' || ch == 'c') {
operand1 = pop(&stack);
switch (ch) {
case '!':
result = 1;
for (int j = 1; j <= operand1; j++) {
result *= j;
}
break;
case 'q':
result = sqrt(operand1);
break;
case 's':
result = sin(operand1);
break;
case 'c':
result = cos(operand1);
break;
default:
printf("Error: unacceptable operator\n");
return 0;
}
}
else {
operand2 = pop(&stack);
operand1 = pop(&stack);
switch (ch) {
case '+':
result = operand1 + operand2;
break;
case '-':
result = operand1 - operand2;
break;
case '*':
result = operand1 * operand2;
break;
case '/':
result = operand1 / operand2;
break;
case '^':
result = pow(operand1, operand2);
break;
default:
printf("Error: unacceptable operator\n");
return 0;
}
}
push(&stack, result);
}
else {
printf("Error: wrong symbol in postfix\n");
return 0;
}
}
result = pop(&stack);
if (!isEmpty(&stack)) {
printf("Error: wrong expression\n");
return 0;
}
return result;
}
int main() {
char infix[MAX_SIZE];
char postfix[MAX_SIZE];
printf("q - sqrt, s - sinus, c - cosinus\n",251);
printf("Enter the expression: ");
fgets(infix, sizeof(infix), stdin);
infix[strlen(infix) - 1] = '\0';
infixToPostfix(infix, postfix);
//printf("Postfix: %s\n", postfix);
float result = evaluatePostfix(postfix);
printf("Result: %.2f\n", result);
return 0;
}
Только для примера a*a(где a - переменная, которую задаёт пользователь) visual studio выдаёт ошибку вот в этом куске.
if (xs[ch] > 0) {
while (isdigit(xs1[ch][k])) {
postfix[j++] = xs1[ch][k++];
}
k = 0;
postfix[j++] = ' ';
}
xs[] - это массив, содержащий повторы символов. xs1[] - двумерный массив из символов и их значений в строковом формате. При дебаге выяснил, что при первоначальном считывании символа всё хорошо. При вторичном считывании берутся пустые значения вообще из другой части xs1[]. Хотя переменная k, указывающая на начало строки символа ch, после всех выполненных операций с числом обнуляется, дабы потом при последующем обращении начать пробегать по строке с самого начала для вторичного считывания числа.