Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define _CRT_SECURE_NO_DEPRECATE
- #include <locale.h>
- #include <math.h>
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
- #define SIZEMAX 256
- #define SIZESTACK 3
- #define EXP "2,7182818"
- #define PI "3,1415926"
- // определение структуры для переменных
- struct _var
- {
- char* name; // имя переменной
- double value; // значение переменной
- };
- // определение имени variable для типа variable
- typedef struct _var var;
- var** varList = NULL; // двойной указатель на массив переменных
- int varCount = 0; // число переменных
- int createVariable(char* varName)
- {
- var* newVar = NULL; // указатель на новую переменную
- varList = realloc(varList, (varCount + 1) * sizeof(var*)); // выделение дополнительной памяти в массиве переменных под новую переменную
- if (varList == NULL) // дополнительная память не была выделена
- {
- return 0;
- }
- newVar = malloc(sizeof(var)); // выделение памяти под новую переменную
- if (newVar == NULL) // дополнительная память не была выделена
- {
- return 0;
- }
- newVar->name = malloc((strlen(varName) + 1) * sizeof(char)); // выделение памяти под имя новой переменной
- if (newVar->name == NULL) // память под имя новой переменной не была выделена
- {
- free(newVar); // очистка памяти под новую переменную
- return 0;
- }
- memset(newVar->name, '\0', (strlen(varName) + 1));
- memcpy(newVar->name, varName, strlen(varName)); // копирование имени новой переменной в структуру
- newVar->value = 0.0; // задание начального значения новой переменной
- varList[varCount] = newVar; // запись новой переменной в массив переменных
- varCount++; // увеличение счетчика количества переменных на 1
- return 1;
- }
- void clearVariables()
- {
- int i = 0; // индексная переменная
- for (i = 0; i < varCount; i++)
- {
- free(varList[i]->name); // очистка памяти под имя переменной
- free(varList[i]); // очистка памяти под значение переменной
- }
- varCount = 0; // обнуление счетчика количества переменных
- return;
- }
- struct _stack
- {
- double* container;
- int size;
- };
- typedef struct _stack stack;
- stack* stackInit()
- {
- stack *newStack;
- newStack = malloc(sizeof(stack));
- if (newStack == NULL)
- {
- return newStack;
- }
- newStack->container = NULL;
- newStack->size = 0;
- return newStack;
- }
- void stackClear(stack** myStack)
- {
- free((*myStack)->container);
- free(*myStack);
- return;
- }
- int stackPush(double value, stack** myStack)
- {
- (*myStack)->size += 1;
- (*myStack)->container = realloc((*myStack)->container, sizeof(double) * (*myStack)->size);
- if ((*myStack)->container == NULL)
- {
- return -1;
- }
- else
- {
- (*myStack)->container[(*myStack)->size - 1] = value;
- return 0;
- }
- }
- double stackPop(stack** myStack)
- {
- double res = 0;
- res = (*myStack)->container[(*myStack)->size - 1];
- (*myStack)->size -= 1;
- (*myStack)->container = realloc((*myStack)->container, sizeof(double) * (*myStack)->size);
- return res;
- }
- double operate(char operator, stack** myStack)
- {
- double op2 = stackPop(myStack);
- double op1 = stackPop(myStack);
- switch (operator)
- {
- case '+':
- return op1 + op2;
- case '-':
- return op1 - op2;
- case '*':
- return op1 * op2;
- case '/':
- return op1 / op2;
- case '^':
- return powf(op1, op2);
- }
- }
- int isOperator(char* str)
- {
- if (strpbrk(str, "+-/*^") != NULL && strlen(str) == 1)
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
- int isNumber(char* str)
- {
- int i = 0; // индексная переменная
- int foundPoint = 0; // флаг найден ли символ разделитель в вещественном числе
- // проходим по всем символам лексемы
- for (i = 0; i < strlen(str); i++)
- {
- if (isdigit(str[i]) == 0) // текущий символ не число
- {
- if (str[i] == ',') // текущий символ - разделитель в вещественном числе
- {
- if (foundPoint == 0) // символ разделитель ранее не встречен
- {
- foundPoint = 1; // флаг - символ разделитель найден
- }
- else
- {
- return 0;
- }
- }
- else
- {
- return 0;
- }
- }
- }
- return 1;
- }
- int validVarName(char* str)
- {
- int i = 0; // индексная переменная
- if (isalpha(str[0]) == 0) // первый символ - не буква
- {
- return 0;
- }
- // проходим по всем элементам лексемы
- for (i = 1; i < strlen(str); i++)
- {
- if (isalnum(str[i]) == 0) // текущий символ - не буква и не число
- {
- return 0;
- }
- }
- return 1;
- }
- char* calc(char* str);
- int parVar(char* str)
- {
- char* tmp = NULL;
- int i = 0;
- int foundVariable = 0;
- int knownVariable = 0;
- tmp = strtok(str, "\t ");
- while (tmp != NULL)
- {
- knownVariable = 0;
- if (strcmp(tmp, "EXP") == 0)
- {
- tmp = strtok(NULL, "\t ");
- continue;
- }
- if (strcmp(tmp, "PI") == 0)
- {
- tmp = strtok(NULL, "\t ");
- continue;
- }
- if (isNumber(tmp) == 0 && isOperator(tmp) == 0)
- {
- if (validVarName(tmp) == 1)
- {
- for (i = 0; i < varCount; i++)
- {
- if (strcmp(tmp,varList[i]->name) == 0)
- {
- knownVariable = 1;
- break;
- }
- }
- if (knownVariable == 1)
- {
- tmp = strtok(NULL, "\t ");
- continue;
- }
- if (createVariable(tmp) == 1)
- {
- foundVariable = 1;
- }
- }
- }
- tmp = strtok(NULL, "\t ");
- }
- return foundVariable;
- }
- int main()
- {
- int i = 0;
- char str[SIZEMAX] = { '\0' };
- setlocale(LC_ALL, "RUS");
- printf("Введите выражение в обратной польской записи.\n");
- printf("Чтобы завершить работу, введите слово ESCAPE.\n\n");
- printf("ВВОД: ");
- gets_s(str, SIZEMAX);
- char *copyStr = malloc(strlen(str) + 1);
- memset(copyStr, '\0', strlen(str) + 1);
- strncpy(copyStr, str, strlen(str));
- if (parVar(copyStr) == 1)
- {
- for (i = 0; i < varCount; i++)
- {
- printf("ВЫВОД: Введите значение переменной %s\n\n", varList[i]->name);
- printf("ВВОД: ");
- scanf("%lf", &varList[i]->value);
- }
- printf("ВЫВОД: %s\n\n", calc(str));
- }
- else
- {
- printf("ВЫВОД: %s\n\n", calc(str));
- }
- clearVariables();
- free(copyStr);
- system("pause");
- return 0;
- }
- char* calc(char* str)
- {
- int strl = strlen(str);
- double res = 0;
- char* tmp = NULL;
- int i = 0;
- int foundVariable = 0;
- stack *myStack = stackInit();
- tmp = strtok(str, "\t ");
- while (tmp != NULL)
- {
- foundVariable = 0;
- if (strcmp(tmp, "EXP") == 0) tmp = EXP;
- if (strcmp(tmp, "PI") == 0) tmp = PI;
- if (isNumber(tmp) == 1)
- {
- stackPush(atof(tmp), &myStack);
- }
- else if (isOperator(tmp) == 1)
- {
- if (myStack->size >= 2)
- {
- stackPush(operate(*tmp, &myStack), &myStack);
- }
- else
- {
- stackClear(&myStack);
- return "Ошибка! Встречен оператор, а количество чисел в стеке меньше двух.";
- }
- }
- else
- {
- for (i = 0; i < varCount; i++)
- {
- // имя переменной в массиве найдено
- if (strcmp(tmp, varList[i]->name) == 0)
- {
- stackPush(varList[i]->value, &myStack);
- foundVariable = 1;
- }
- }
- if (foundVariable == 0)
- {
- stackClear(&myStack);
- return "Ошибка! Недопустимое выражение.";
- }
- }
- tmp = strtok(NULL, "\t ");
- }
- if (myStack->size != 1)
- {
- stackClear(&myStack);
- return "Ошибка! После завершения вычислений в стеке содержится не единственное число.";
- }
- res = stackPop(&myStack);
- stackClear(&myStack);
- memset(str, '\0', SIZEMAX);
- sprintf(str, "%lf", res);
- return str;
- }
Add Comment
Please, Sign In to add comment