Строковый калькулятор

Автор работы: Пользователь скрыл имя, 25 Августа 2013 в 18:52, курсовая работа

Описание работы

Задачей курсовой работы является написание строкового калькулятора. Строковый калькулятор позволяет вычислять математические выражения, введенные пользователем в строку, например: (12-34)*5+19/4.
Строковый калькулятор поддерживает операции сложения (+), вычитания (-), умножения (*), деления (/) и возведения в степень (^).
В основе работы строкового калькулятора лежит преобразование выражения в обратную польскую запись и дальнейшее его вычисление.

Файлы: 1 файл

КУРСАЧ.docx

— 39.37 Кб (Скачать файл)

      // если в итоге стек оказался пустым, приоритет его символов = 0

                            if (stck == "")

                                priorStack = 0;

                            else

    // если стек не пустой, переопределяем приоритет последнего символа

                                priorStack = priorOfSymbol(stck[stck.length() - 1]);

                        }

   // исключаем открывающую скобку из стека

                        stck = stck.substr(0, stck.length() - 1);

                        if (stck == "")

                            priorStack = 0;

                        else

                            priorStack = priorOfSymbol(stck[stck.length() - 1]);

                    }

// если символ не является закрывающей скобкой

                    else

                    {

// если открывающая скобка, записываем ее в стек

                        if (prior == 1)

                        {

                            stck += chS;

                            priorStack = prior;

                        }

// если другой символ

                        else

                        {

            // до тех пор, пока приоритет символа меньше приоритета последнего

         // символа в стеке, переносим символы из стека в строку результата

                            while (prior <= priorStack)

                            {

                                poland += stck.substr(stck.length() - 1, 1);

                                stck = stck.substr(0, stck.length() - 1);

                                if (stck == "")

                                    priorStack = 0;

                                else

                                    priorStack = priorOfSymbol(stck[stck.length() - 1]);

                            }

                            stck += chS;

                            priorStack = prior;

                        }

                    }

                }

            }

// в конце переписывем все оставшиеся в стеке символы в строку результата

            for (int f = 0; f < stck.length(); f++)

            {

                poland += stck[stck.length() - 1 - f];

            }

            return poland;

}

 

 

//-------------------------------------------------------------------------------------------------------

//                      функция вычисления результата

//-------------------------------------------------------------------------------------------------------

// в качестве параметров передается строка соответствующего выражения и массив

// элементов типа Symbol, который хранит соответствие между символами в выражении и

// их численными значениями

//-------------------------------------------------------------------------------------------------------

double calcResult(string str,Symbol *sym,int n)

 {

            double r = 0;    // результат

            double r1 = 0;  // первый операнд

            double r2 = 0;  // второй операнд

            char operation; // операция

            int sInt = 0;     // индекс элемента массива, в котором хранится результат

    // выполнения текущей операции

 

 

            for (int i = 0; i < str.length(); i++)

            {

                // определение типа операции

                if (str[i] == '+' || str[i] == '-' || str[i] == '*' ||

                    str[i] == '/' || str[i] == '^')

                {

                    operation = str[i];

 

                    // получение первого и второго операндов

                    for (int l = 0; l <= n; l++)

                    {

                        if (sym[l].symb == str[i - 2])

                        {

                            r1 = sym[l].val;

                        }

    if (sym[l].symb == str[i - 1])

                        {

                            r2 = sym[l].val;

                          // результат записывается на место второго операнда

                            sInt = l;

                        }

                    }

                   

// в зависимости от операции, выполняем соответствующее действие

                    switch (operation)

                    {

                        case '+':

                            r = r1 + r2;

                            break;

                        case '-':

                            r = r1 - r2;

                            break;

                        case '*':

                            r = r1 * r2;

                            break;

                        case '/':

                            r = r1 / r2;

                            break;

                        case '^':

// при попытке вычислить дробную степень из отрицательного числа (т.е. корень)

// в результат записывается значение NULL, что в последствие приведет к выводу

// сообщения об ошибке

                            if ((r1 < 0)&&((r2>-1)&&(r2<1)))

                            r = NULL;

                            else

                            r = pow(r1, r2);

                            break;

                    }

// последняя операция производится, когда остается 3 элемента в массиве (2 операнда

// и символ операции, далее вычисления не производятся

                    if (str.length() == 3)

                        break;

 

 // после выполнения текущей операции, записываем результат на место второго

// операнда и получаем новую строку вычисляемого выражения

                    if (i > 2)

                        str = str.substr(0, i - 2) + str[i - 1] + str.substr(i + 1, str.length() - i - 1);

                    else

                        str = str[i - 1] + str.substr(i + 1, str.length() - 3);

                    sym[sInt].val = r;

                    i = 0;

                }

            }

            return r;

}

 

//--------------------------------------------------------------------------------------------

//   функция преобразования строки в выражение и вычисления его значения

//---------------------------------------------------------------------------------------------

        double convertAndCalc(string str)

        {

 

// массив для хранения данных о символах в выражении и их числовых значениях 

Symbol *sym = new Symbol[str.length()];

int j = 0;

         // first char = 'a', fNum, lNum - bounds of values

            char ch = 'a';    // первый символ равен 'a'

            int fNum = 0, lNum = -1;  // первый и последний элементы в строке,

                                                   // определяющие границы числа

            string result = "";             // результат преобразования строки пользователя в

                                                  // выражение

 

 

 

for (int i = 0; i < str.length(); i++)

{

  // допустимые символы в выражении – цифры и символы операций, если выражение

// содержит иные символы или два символа операции подряд, результат будет равен

//  NULL, а пользователю выведется сообщение об ошибке             

       if(((str[i]<40)||(str[i]==44)||(str[i]==46)||(str[i]>57&&str[i]<94)||(str[i]>95))        

           ||(isOperation(str[i])&&isOperation(str[i+1])))

                {   

                return NULL;

                }

// если символ – операция, получаем предшествующее ей  число (границы числа fNum и

// lNum. Если символ не операция, правая граница числа (lNum) = текущему символу

               

                if (str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/' ||

                    str[i] == '^' || str[i] == '(' || str[i] == ')')

                {

                    if (lNum >= fNum)

                    {

                        // записываем информацию о числе в массив

   double val = atof(str.substr(fNum, lNum - fNum + 1).c_str());

   sym[j].symb = ch;

 sym[j].val = val;

                    ch++;

                    j++;

                    }

                    // записываем информация об операции в массив

sym[j].symb = str[i];

sym[j].val = 0;

                    j++;

                    fNum = i + 1;

                }

                else

                    lNum = i;

            }

 

            // записываем информацию о последнем числе в массив

            if (lNum >= fNum)

            {

                double v = atof(str.substr(fNum, lNum - fNum + 1).c_str());

          sym[j].symb = ch;

      sym[j].val = v;

                ch++;

                j++;

            }

 

            // записываем полученное выражение в строку результата

            for (int i = 0; i < j; i++)

            {

                result += sym[i].symb;

            }

 

 

 // если выражение содержит участки вида ‘(-a’ или начинается с ‘-а’, они заменяются

// на 'a', но при этом  числовое значение меняет знак на противоположный

for (int i = 0; i < result.length() - 2; i++)

            {

                if (result[i] == '(' && result[i + 1] == '-')

                {

sym[i + 2].val = -sym[i + 2].val;

                    result = result.substr(0, i + 1) + result.substr(i + 2, result.length() - i - 2);

                }

            }

 

            if (result[0] == '-')

            {

                sym[1].val = -sym[1].val;

                result = result.substr(1);

            }

// если число открытых скобок не равно числу закрытых скобок, возвращаем NULL

// (выводим сообщение об ошибке в выражении)

  int numOfOpen = 0, numOfClosed = 0;

             for (int i = 0; i < result.length(); i++)

            {

                if (result[i] == '(')

                numOfOpen++;

                if (result[i] == ')')

                numOfClosed++;

            }

            if (numOfOpen != numOfClosed)

            return NULL;

 

 

// полученное выражение преобразуем в обратную польскую запись

            string poland = convertToPoland(result);

// вычисляем значение выражения

            double r = calcResult(poland,sym,j);

// освобождаем память выделенную под массив sym

    delete[] sym;

            return r;

       }


Информация о работе Строковый калькулятор