Paste will expire never.
- #include <iostream>
- #include <cmath>
- #include <string.h>
- using namespace std;
- const int MAX_SIZE = 200+10;
- const int MAX_FUNC_NAME = 3;
- char* funcName[] = {"sin","cos",0};
- double (*pfuncs[])(double) = {sin,cos};
- bool ReadExp(char* &pos, double &res);
- inline void SkipSpaces(char* &pos) {
- while (*pos == ' ')
- pos++;
- }
- inline bool isPlusOrMinus(char* &pos) {
- //1. Пробелы могут быть: перед +,-
- SkipSpaces(pos);
- return '+' == *pos || '-' == *pos;
- }
- inline bool isMulOrDiv(char* &pos) {
- // 2. Пробелы могут быть: перед *,/
- SkipSpaces(pos);
- return '*' == *pos || '/' == *pos;
- }
- inline bool isLetter(char* &pos) {
- return
- ('A' <= *pos && *pos <='Z') ||
- ('a' <= *pos && *pos <='z');
- }
- inline bool isDigit(char* &pos) {
- // <Цифра> = 0|1|2|3|4|5|6|7|8|9|
- return '0' <= *pos && *pos <= '9';
- }
- inline bool isOpenBracket(char* &pos) {
- // 3. Пробелы могут быть: перед (
- SkipSpaces(pos);
- return '(' == *pos;
- }
- inline bool isCloseBracket(char* &pos) {
- // 4. Пробелы могут быть: перед )
- SkipSpaces(pos);
- return ')' == *pos;
- }
- bool isFuncBegin(char* &pos) {
- // 6. Пробелы могут быть: перед именем функции
- SkipSpaces(pos);
- return isLetter(pos);
- }
- int FuncPos(char* fName) {
- int pos = -1;
- for (int i=0; funcName[i]!=0; i++) {
- if (!strcmp(funcName[i],fName))
- return i;
- }
- return pos;
- }
- bool isFracNumBegin(char* &pos) {
- // 5. Пробелы могут быть: перед числом
- SkipSpaces(pos);
- return isDigit(pos);
- }
- bool ReadFuncName(char* &pos, int &funcPos) {
- // <ИмяФункции> = "sin"|"cos"
- char* fName = new char[MAX_FUNC_NAME+1];
- int fNameLen = 0;
- while (isLetter(pos)) {
- fNameLen++;
- pos++;
- }
- if (fNameLen>MAX_FUNC_NAME)
- return false;
- // копирование происходит с учетом регистра
- strncpy(fName,pos-fNameLen,fNameLen);
- fName[fNameLen] = 0;
- funcPos = FuncPos(fName);
- return funcPos != -1;
- }
- bool ReadFunc(char* &pos, double &res) {
- // <Функция> = <ИмяФункции>(<Выражение>)
- int funcPos = 0;
- if (!ReadFuncName(pos, funcPos))
- return false;
- if (isOpenBracket(pos)) {
- pos++;
- double arg = 0;
- if (!ReadExp(pos,arg))
- return false;
- if (!isCloseBracket(pos))
- return false;
- pos++;
- res = pfuncs[funcPos](arg);
- return true;
- }
- else
- return false;
- }
- bool ReadFracNum(char* &pos, double &res) {
- // <ДробноеЧисло> = <ЦелаяЧасть>|<ЦелаяЧасть>.<ДробнаяЧасть>
- // <ЦелаяЧасть> = <Цифра>|<Цифра><Цифра>
- double intPart = 0;
- do
- {
- if (!isDigit(pos))
- return false;
- intPart = intPart*10 + *pos - '0';
- pos++;
- }
- while (isDigit(pos));
- // <ДробнаяЧасть> = <Цифра>|<Цифра><Цифра>
- double dblPart = 0;
- if (*pos == '.') {
- pos++;
- double pow = 10;
- do
- {
- if (!isDigit(pos))
- return false;
- dblPart += (*pos - '0') / pow;
- pow *=10;
- pos++;
- } while (isDigit(pos));
- }
- res = intPart + dblPart;
- return true;
- }
- bool ReadMul(char* &pos, double &res) {
- // <Множитель> = +|- <ДробноеЧисло>|<Функция>|(<Выражение>)
- bool isNeg = false;
- if (isPlusOrMinus(pos)) {
- isNeg = *pos == '-';
- pos++;
- }
- if (isFracNumBegin(pos)) {
- if (!ReadFracNum(pos,res))
- return false;
- }
- else if (isFuncBegin(pos)) {
- if (!ReadFunc(pos,res))
- return false;
- }
- else if (isOpenBracket(pos)) {
- pos++;
- if (!ReadExp(pos,res))
- return false;
- if (!isCloseBracket(pos))
- return false;
- pos++;
- }
- else
- return false;
- res *= isNeg ? -1 : 1;
- return true;
- }
- bool ReadOper(char* &pos, char &oper) {
- oper = *pos++;
- return true;
- }
- bool ReadTerm(char* &pos, double &res) {
- // <Слагаемое> = <Множитель>{*|/<Множитель>}
- if (!ReadMul(pos, res))
- return false;
- while (isMulOrDiv(pos)) {
- char oper = 0;
- if (!ReadOper(pos,oper))
- return false;
- double cur = 0;
- if(!ReadMul(pos,cur))
- return false;
- switch(oper) {
- case '*': res *= cur; break;
- case '/': res /= cur; break; // деление на ноль не будет по условию
- }
- }
- return true;
- }
- bool ReadExp(char* &pos, double &res) {
- // <Выражение> = <Слагаемое>{+|-<Слагаемое>}
- do
- {
- double cur = 0;
- if (!ReadTerm(pos,cur))
- return false;
- else
- res += cur;
- }
- while (isPlusOrMinus(pos));
- // 7. Пробелы могут быть: в конце выражения
- SkipSpaces(pos);
- return 0 == *pos || isCloseBracket(pos);
- }
- void input() {
- char* buf = new char[MAX_SIZE];
- memset(buf,0,sizeof(buf));
- gets(buf);
- int initAddress = (int)buf;
- double res = 0.0;
- if (ReadExp(buf,res))
- printf("%0.3f",res);
- else
- printf("Error");
- buf = (char*) initAddress;
- delete [] buf;
- }
- int main() {
- freopen("input.txt","r",stdin);
- freopen("output.txt","w",stdout);
- input();
- return 0;
- }
Editing is locked.