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>
- #include <stdlib.h>
- #define SIZE 64
- #define EXP "2,7182818"
- #define PI "3,1415926"
- // определение структуры для переменных
- struct _var
- {
- char* name; // имя переменной
- double value; // значение переменной
- };
- // определение имени var для типа _var
- typedef struct _var var;
- // определение структуры для стека
- struct _stack
- {
- double* container; // массив значений
- int size; // размер стека
- };
- // определение имени stack для типа _stack
- typedef struct _stack stack;
- // функция выделения памяти под стек
- stack* stackInit();
- // функция очистки стека
- void stackClear(stack** myStack);
- //функция записи значения в стек
- int stackPush(double value, stack** myStack);
- // функция вывода элемента из стека
- double stackPop(stack** myStack);
- // функция создания новой переменной
- int createVariable(char* varName, var*** varList, int* varCount);
- // функция очистки переменных
- void clearVariables(var*** varList, int* varCount);
- // функция выполнения математических операций
- double operate(char operator, stack** myStack, int* errCode);
- // функция проверки лексемы на принадлежность к операторам
- int isOperator(char* str);
- // функция проверки является ли лексема числом
- int isNumber(char* str);
- // функция проверки может ли лексема являться именем переменной
- int validVarName(char* str);
- // функция возвращает результат вычислений в случае успеха или код ошибки в случае неудачи
- double calc(char* str, int* errCode, var*** varList, int* varCount);
- // функция поиска в строке имен переменных
- int parsStr(char* str, var*** varList, int* varCount);
- // функция вывода сообщения об ошибке
- void printError(int errCode);
- char* readStr(int *checkError);
- // функция выводит результат вычислений в случае успеха или текст сообщения об ошибке в случае неудачи
- void main()
- {
- var** varList = NULL; // двойной указатель на массив переменных
- int varCount = 0; // число уникальных переменных
- char* valueS = NULL; // указатель на буффер под значение переменной
- int checkError = 0; // флаг ошибки
- double result = 0; // результат вычислений
- int i = 0; // индексная переменная
- char* str = NULL; // указатель на строку с выражением
- char* copyStr = NULL; // указатель на копию строки с выражением
- setlocale(LC_ALL, "RUS");
- printf("Введите выражение в обратной польской записи\n");
- printf("ВВОД: ");
- str = readStr(&checkError); // считывание строки с выражением
- if(checkError == 0) // ошибок не найдено
- {
- copyStr = malloc(strlen(str) + 1); // выделение памяти под копию считанной строки
- if (copyStr == NULL) // память под копию строки не была выделена
- {
- checkError = -1;
- printError(checkError); // вывод сообщения об ошибке
- return;
- }//if
- strcpy(copyStr, str); // копирование строки str в strcopy
- checkError = parsStr(copyStr, &varList, &varCount); // функция находит имена переменных в строке и возвращает флаг ошибки
- if (checkError == 0) // ошибок не найдено
- {
- // считывание значений переменных
- for (i = 0; i < varCount; i++)
- {
- printf("\nВЫВОД: Введите значение переменной %s\n", varList[i]->name);
- printf("ВВОД: ");
- valueS = malloc(SIZE); // выделение памяти под значение переменной
- if (valueS == NULL) // проверка выделения памяти под значение переменной
- {
- checkError = -1;
- break;
- }//if
- valueS = readStr(&checkError); // считывание значения переменной
- if (isNumber(valueS) == 1) // считанное значение является числом
- {
- varList[i]->value = atof(valueS); // запись соответствующего значения переменной в масссив переменных
- }//if
- else
- {
- checkError = 3; // в качестве значения переменной введено не число
- free(valueS); // очистка памяти для считывания значения переменной
- break;
- }//else
- free(valueS); // очистка памяти для считывания значения переменной
- }//for
- if (checkError == 0) // ошибок не найдено
- {
- result = calc(str, &checkError, &varList, &varCount); // присвоение результата вычислений
- if (checkError == 0) // ошибок не выявлено
- {
- printf("\nРезультат: %lf\n\n", result);
- }//if
- }//if
- }//if
- }// if
- printError(checkError); // вывод сообщения об ошибке
- clearVariables(&varList, &varCount); // очистка известных переменных
- if (copyStr != NULL) // если память под копию выделена
- {
- free(copyStr); // очистка памяти под копию считанной строки
- }
- system("pause");
- return ;
- }//main
- stack* stackInit()
- {
- stack* newStack; // указатель на новый стек
- newStack = malloc(sizeof(stack)); // выделение памяти под новый стек
- if (newStack == NULL) // память под стек не была выделена
- {
- return newStack;
- }//if
- newStack->container = NULL; // инициализация массива стека
- newStack->size = 0; // инициализация размера стека
- return newStack;
- }//stackInits
- void stackClear(stack** myStack)
- {
- free((*myStack)->container); // очистка массива стека
- free(*myStack); // удаление указателя на стек
- return;
- }//stackClear
- int stackPush(double value, stack** myStack)
- {
- (*myStack)->size += 1; // увеличение размера стека на 1
- (*myStack)->container = realloc((*myStack)->container, sizeof(double) * (*myStack)->size); // выделение памяти под новый элемент стека
- if ((*myStack)->container == NULL) // память не была выделена
- {
- return -1;
- }//if
- else
- {
- (*myStack)->container[(*myStack)->size - 1] = value; // запись нового значения в стек
- return 0;
- }//else
- }//stackPush
- double stackPop(stack** myStack)
- {
- double res = 0;
- res = (*myStack)->container[(*myStack)->size - 1]; // присвоение res последнего значения из стека
- (*myStack)->size -= 1; // уменьшени размера стека на 1
- (*myStack)->container = realloc((*myStack)->container, sizeof(double) * (*myStack)->size); // уменьшение выделенной памяти под стек
- return res;
- }//stackPop
- int createVariable(char* varName, var*** varList, int* varCount)
- {
- var* newVar = NULL; // указатель на новую переменную
- *varList = realloc(*varList, (*varCount + 1) * sizeof(var*)); // выделение дополнительной памяти в массиве переменных под новую переменную
- if (*varList == NULL) // дополнительная память не была выделена
- {
- return -1;
- }//if
- newVar = malloc(sizeof(var)); // выделение памяти под новую переменную
- if (newVar == NULL) // дополнительная память не была выделена
- {
- return -1;
- }//if
- newVar->name = malloc((strlen(varName) + 1) * sizeof(char)); // выделение памяти под имя новой переменной
- if (newVar->name == NULL) // память под имя новой переменной не была выделена
- {
- free(newVar); // очистка памяти под новую переменную
- return -1;
- }//if
- memset(newVar->name, '\0', (strlen(varName) + 1)); // можно использовать strcat, strncat
- memcpy(newVar->name, varName, strlen(varName)); // копирование имени новой переменной в структуру
- newVar->value = 0.0; // задание начального значения новой переменной
- (*varList)[*varCount] = newVar; // запись новой переменной в массив переменных
- (*varCount)++; // увеличение счетчика количества переменных на 1
- return 0;
- }//createVariable
- void clearVariables(var ***varList, int *varCount)
- {
- int i; // индексная переменная
- for (i = 0; i < *varCount; i++)
- {
- free((*varList)[i]->name); // очистка памяти под имя переменной
- free((*varList)[i]); // очистка памяти под значение переменной
- }//for
- varCount = 0; // обнуление счетчика количества переменных
- return;
- }//clearVariables
- double operate(char operator, stack** myStack, int* errCode)
- {
- double op2 = stackPop(myStack);
- double op1 = stackPop(myStack);
- switch (operator)
- {
- case '+':
- return op1 + op2;
- case '-':
- return op1 - op2;
- case '*':
- return op1 * op2;
- case '/':
- if (op2 == 0) // деление на 0
- {
- *errCode = 2;
- return;
- }//if
- else return op1 / op2;
- case '^':
- if (op1 == 0 && op2 < 0) // деление на 0
- {
- *errCode = 2;
- return;
- }//if
- else return pow(op1, op2);
- }//switch
- }//operate
- int isOperator(char* str)
- {
- // в лексеме найден символ принадлежащий к списку операторов и длина лексемы 1
- return (strpbrk(str, "+-/*^") != NULL && strlen(str) == 1) ? 1 : 0;
- }//isOperator
- int isNumber(char* str)
- {
- int i; // индексная переменная
- int foundPoint = 0; // флаг найден ли символ разделитель в вещественном числе
- // проходим по всем символам лексемы
- for (i = 0; i < strlen(str); i++)
- {
- if (isdigit(str[i]) == 0) // текущий символ не число
- {
- if (str[i] == '-' && i == 0 && strlen(str) != 1)
- {
- continue;
- }//if
- else
- {
- if (str[i] == ',') // текущий символ - разделитель в вещественном числе
- {
- if (foundPoint == 0) // символ разделитель ранее не встречен
- {
- foundPoint = 1; // флаг - символ разделитель найден
- }//if
- else
- {
- return 0;
- }//else
- }//if
- else
- {
- return 0;
- }//else
- }//else
- }//if
- }//for
- return 1;
- }// isNumber
- int validVarName(char* str)
- {
- int i; // индексная переменная
- if (isalpha(str[0]) == 0) // первый символ - не буква
- {
- return 0;
- }//if
- // проходим по всем элементам лексемы
- for (i = 1; i < strlen(str); i++)
- {
- if (isalnum(str[i]) == 0) // текущий символ - не буква и не число
- {
- return 0;
- }//if
- }//for
- return 1;
- }//validVarName
- double calc(char* str, int* errCode, var ***varList, int *varCount)
- {
- double res = 0.0; // результат вычислений
- char* tmp = NULL; // указатель на лексему
- int i; // индексная переменная
- stack* myStack = stackInit(); // создание стека
- if (myStack == NULL) // память под стек не была выделена
- {
- *errCode = -1;
- return res;
- }//if
- tmp = strtok(str, "\t "); // считывание лексемы
- while (tmp != NULL) // найдена лексема
- {
- if (strcmp(tmp, "EXP") == 0) tmp = EXP;
- if (strcmp(tmp, "PI") == 0) tmp = PI;
- if (isNumber(tmp) == 1) // лексема - число
- {
- stackPush(atof(tmp), &myStack); // запись числа в стек
- }//if
- else if (isOperator(tmp) == 1) // лексема - оператор
- {
- if (myStack->size >= 2) // в стеке 2 числа или более
- {
- stackPush(operate(*tmp, &myStack, errCode), &myStack); // в стек результата операции
- }//if
- else
- {
- stackClear(&myStack); // очистка стека
- *errCode = 1;
- return res;
- }//else
- }//else if
- else // встречена переменная
- {
- for (i = 0; i < *varCount; i++)
- {
- // имя переменной в массиве переменных найдено
- if (strcmp(tmp, (*varList)[i]->name) == 0)
- {
- stackPush((*varList)[i]->value, &myStack); // запись значения переменной в стек
- }//if
- }//for
- }//else
- tmp = strtok(NULL, "\t "); // переход к следующей лексеме
- }//while
- res = stackPop(&myStack);
- stackClear(&myStack);
- return res;
- }//calc
- int parsStr(char* str, var*** varList, int* varCount )
- {
- int operandCount = 0; // число операндов
- int operateCount = 0; // число операторов
- char* tmp = NULL; // указатель на лексему
- int i; // индексная переменная
- int indicator = 0; // код завершения функции
- int knownVariable = 0; // флаг уникальности переменной
- tmp = strtok(str, "\t "); // считывание лексемы
- while (tmp != NULL)
- {
- knownVariable = 0;
- if (strcmp(tmp, "EXP") == 0) // лексема - экспонента
- {
- tmp = strtok(NULL, "\t "); // указатель на следующую лексему
- operandCount++; // увеличение на 1 счетчика числа операндов
- continue;
- }//if
- if (strcmp(tmp, "PI") == 0) // лексема - число Пи
- {
- tmp = strtok(NULL, "\t "); // указатель на следующую лексему
- operandCount++; // увеличение на 1 счетчика числа операндов
- continue;
- }//if
- if (isOperator(tmp) == 1) // лексема - оператор
- {
- operateCount++; // увеличение на 1 счетчика числа операторов
- }//if
- else if (isNumber(tmp) == 1) // лексема - число
- {
- operandCount++; // увеличение на 1 счетчика числа операндов
- }//else if
- else if (validVarName(tmp) == 1) // может ли лексема являться именем переменной
- {
- operandCount++; // увеличение на 1 счетчика числа операндов
- // проверка имени переменной на уникальность
- for (i = 0; i < *varCount; i++)
- {
- if (strcmp(tmp, (*varList)[i]->name) == 0) // переменная не уникальна
- {
- knownVariable = 1;
- break;
- }//if
- }//for
- if (knownVariable == 1)
- {
- tmp = strtok(NULL, "\t "); // указатель на следующую лексему
- continue;
- }//if
- else indicator = createVariable(tmp, varList, varCount); // флаг создалась ли переменная: 0 - да, -1 - нет
- }//else if
- else
- {
- indicator = -2; // флаг -2, встречена неизвестная лексема
- return indicator;
- }//else
- tmp = strtok(NULL, "\t "); // указатель на следующую лексему
- }//while
- if (operateCount != operandCount - 1) // недостаточное число операторов или операндов
- {
- indicator = -3;
- }//if
- return indicator;
- }//parsStr
- void printError(int errCode)
- {
- switch (errCode)
- {
- case 0:
- return;
- case -1:
- printf("\nОшибка! Невозможно выделить память\n\n");
- return;
- case -2:
- printf("\nОшибка! Встречена неизвестная лексема\n\n");
- return;
- case -3:
- printf("\nОшибка! Недостаточно операторов или операндов\n\n");
- return;
- case 1:
- printf("\nОшибка! Встречен оператор, а количество операндов в стеке меньше двух\n\n");
- return;
- case 2:
- printf("\nОшибка! Деление на 0\n\n");
- return;
- case 3:
- printf("\nОшибка! Недопустимое значение переменной\n\n");
- return;
- case 4:
- printf("\nОшибка! Неудачная попытка чтения строки\n\n");
- return;
- default:
- printf("\nНеизвестный код ошибки.\n\n");
- return;
- }//switch
- }//printError
- char* readStr(int* errCode)
- {
- char* pos = NULL; // указатель на элемент в строке
- int i = 1; // индексная переменная
- char tmp[SIZE]; // буфер под считываемую строку на SIZE символов
- char* check;
- char* s = malloc(SIZE); // выделение памяти строку
- if (s == NULL) // проверка выделения памяти
- {
- *errCode = -1;
- }//if
- check = fgets(s, SIZE, stdin); // считывание из консоли строки размера SIZE в s
- if (check == NULL)
- {
- *errCode = 4;
- }//if
- if ((pos = strrchr(s, '\n')) != NULL) // в s найден символ перехода на новую строку
- {
- *pos = 0;
- return s;
- }//if
- while (1)
- {
- i++;
- check = fgets(tmp, SIZE, stdin); // // считывание из консоли части строки размера SIZE в tmp
- if (check == NULL)
- {
- *errCode = 4;
- }//if
- if ((pos = strrchr(tmp, '\n')) != NULL) // в tmp найден символ перехода на новую строку (конец всей строки)
- {
- *pos = 0; // удаление символа перехода на новую строку
- s = realloc(s, SIZE * i); // выделение дополнительной памяти в s
- if (s == NULL) // проверка выделения памяти
- {
- *errCode = -1;
- }//if
- strcat(s, tmp); // склеивание начала строки и ее конца
- break;
- }//if
- else
- {
- s = realloc(s, SIZE * i); // выделение дополнительной памяти в s
- if (s == NULL) // проверка выделения памяти
- {
- *errCode = -1;
- }//if
- strcat(s, tmp); // склеивание начала строки и ее продолжения
- }//else
- }//while
- return s;
- }
Add Comment
Please, Sign In to add comment