Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

Написать строковый калькулятор - C++

Войти
Регистрация
Восстановить пароль
Другие темы раздела
C++ Бинарное дерево поиска http://www.cyberforum.ru/cpp-beginners/thread837092.html
Пишу программу - Бинарное дерево поиска для Bag class. Заголовочный файл: #ifndef BAG6_H #define BAG6_H #include <cstdlib> // Provides NULL and size_t #include "bintree.h" // Provides...
C++ Перегрузка оператора умножения числа на матрицу Доброго дня суток. Хочу перегрузить оператор умножение числа на матрицу. Перегрузил сначала в классе вот так: matrix operator*(const double ); а вне класса(в том же хидере) написал вот так:... http://www.cyberforum.ru/cpp-beginners/thread837071.html
Некорректность работы программы при считывании текстовых данных с файла C++
Здравствуйте!) Помогите, пожалуйста, решить данную проблему... Почему при следующем варианте кода, программа просто-напросто не работает и вылетает. В чём ошибка при считывании? Подскажите,...
Работа с tinyxml ошибки LNK 2019 и LNK 2001 C++
всем привет! скачал архив tinyxml, разархивировал в папку проекта затем написал следующий код: #include "stdafx.h" #include "tinyxml/tinyxml.h" #include <iostream> int _tmain(int argc,...
C++ Узнать указывает ли указатель http://www.cyberforum.ru/cpp-beginners/thread837020.html
Доброго времени суток. Постановка задачи такова: есть указатель на массив, надо удалить массив, а потом создать новый, но не ясно указывает ли указатель уже куда-то. Как с этим побороться? Спасибо!
C++ Сортировка Нужно написать алгоритмы для Selection, Insertion, Shell, Quick, Merge, Heap сортировок для любых типов данных. Например, сравнить машины и их объемы двигателей. Сам начинающий, не знаю, как сделать.... подробнее

Показать сообщение отдельно
Rifle
26 / 26 / 5
Регистрация: 15.11.2012
Сообщений: 93
Завершенные тесты: 4
14.04.2013, 01:26
Вот готовый пример калькулятора, не используя стек, а просто обрабатывая строку.
Сложение, вычитание, умножение, деление, возведение в степень, скобочки, тригонометрические функции (sin, cos, tang). При желании можно добавить еще что-нибудь.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
#include <iostream>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cmath>
using std::cin;
using std::cout;
using std::endl;
#include "Windows.h"
 
void eatspaces(char* str); //функция для удаления пробелов
double expr(char* str); //функция, вычисляющая выражение
double term(char* str, int& index); //функция для анализа элемента
double trigon(char* str, int& index); //функция для вычисления тригонометрических значений
double power(char* str, int& index); //функция для извлечения степени
double number(char* str, int& index); //функция, распознающая число
char* extract(char* str, int& index); //функция для извлечения подстроки
 
const int MAX = 80; //максимальный размер буфера
 
int main()
    {
    setlocale(0, "Russian");
    char buffer[MAX] = {0}; //область хранения вычисляемого входного выражения
    cout << endl << "Добро пожаловать в дружественный колькулятор!" << endl
         << "Введите выражение или пустую строку для завершения." << endl;
    for ( ; ; )
        {
        cin.getline(buffer, sizeof buffer); //читаем входную строку
        eatspaces(buffer); //удаляем все пробелы из строки
        if (!buffer[0]) //если пустая строка
            return 0;
        cout << "= " << expr(buffer)
             << endl << endl;
        }
    }
        
void eatspaces(char* str)
    {
    int i = 0;                          //индекс места в строке "куда копировать"
    int j = 0;                          //индекс места в строке "откуда копировать"
    while ((*(str+i) = *(str + j++)) != '\0') //цикл, пока очередной символ не '\0'
        if (*(str+i) != ' ')  //увеличиваем i, если символ не пробел
            i++;
    return;
    }
    
double expr(char* str)
    {
    double value = 0.0;         //здесь сохраняем результат
    int index = 0;              //текущая позиция символа
    value = term(str, index);   //получить первый элемент
    for ( ; ; )                 //бесконечный цикл, выход внутри
        {
        switch (*(str+index++)) //выбрать действие на основе текущего символа
            {
            case '\0':          //конец строки, возвращаем значение
                return value;
            case '+':           //знак плюс, прибавляем элемент к value
                value += term(str, index);
                break;
            case '-':           //знак минус, вычитаем элемент из value
                value -= term(str, index);
                break;
            default:            //все остальное не котируется
                int i = index;
                while (--i > 0)
                    cout << " ";
                cout << "^" << endl;
                cout << "Эй, повнимательней можно?! Здесь обнаружена ошибка. " << endl;
                exit(1);
            }
        }
    }
    
double term(char* str, int& index)
    {
    double value = 0.0;             //здесь накапливается значение результата
    value = power(str, index);      //получить первое число элемента
    //выполняем цикл до тех пор, пока имеем допустимую операцию
    while ((*(str + index) == '*') || (*(str + index) == '/')) 
        {
        if (*(str+index) == '*')
            value *= power(str, ++index);
        if (*(str+index) == '/')
            value /= power(str, ++index);
        }
    return value;
    }
    
    
double power(char* str, int& index)
    {
    double value = 0.0;
    value = trigon(str, index);
    while (*(str + index) == '^')
        {
        value = pow(value, trigon(str, ++index)); //возводим в степень
        }
    return value;
    }   
 
double trigon(char* str, int& index)
    {
    int buf_index = 0;
    int temp_index = index; //переменная для хранения индекса (чтобы если что вернуть индекс без изменений)
    char* p_str = 0;    //временный указатель для сравнения символов
    double value = 0;
    while (isalpha(*(str + temp_index)))
        {
        buf_index++;    //сколько букв
        temp_index++;   //текущий индекс
        }
    if (!buf_index)     //если нет ни одной буквы, то возвращаем число
        {
        value = number(str, index);
        return value;
        }
    else                //иначе смотрим, являются ли буквы чем-нибудь этим
        {
        p_str = new char[buf_index+1];  //а для этого создаем временную строку, чтобы сравнить
        p_str[buf_index] = '\0';
        strncpy(p_str, str+index, buf_index);
        }
    if (strcmp(p_str, "sin") == 0)      //синус в градусах
        {
        value = sin(3.141592/180*number(str, temp_index));
        index = temp_index;
        delete[] p_str;     //не забываем удалить временную строку
        return value;
        }
    else if (strcmp(p_str, "cos") == 0) //косинус в градусах
        {
        value = cos(3.141592/180*number(str, temp_index));
        index = temp_index;
        delete[] p_str;     //не забываем удалить временную строку
        return value;
        }
    else if (strcmp(p_str, "tan") == 0) //тангенс в градусах
        {
        value = tan(3.141592/180*number(str, temp_index));
        index = temp_index;
        delete[] p_str;     //не забываем удалить временную строку
        return value;
        }
    else
        {
        return value;
        }
    }
    
double number(char* str, int& index)
    {
    double value = 0.0;                 //хранит результирующее значение
    if (*(str + index) == '(')
        {
        char* p_substr = 0;
        p_substr = extract(str, ++index);
        value = expr(p_substr);
        delete[] p_substr;
        return value;
        }
    //продуманский цикл, превращает символы в число
    while (isdigit(*(str+index)))       //цикл накапливает ведущие цифры 
        value = 10*value + (*(str + index++) - '0');
    if (*(str + index) != '.')          //если не цифра, проверяем на десятичную точку
        return value;
    double factor = 1.0;                //множитель для десятичных разрядов
    //еще один продуманский цикл, возвращает десятичную часть
    while (isdigit(*(str + (++index)))) //выполнять цикл, пока идут цифры 
        {
        factor *= 0.1;
        value = value + (*(str + index) - '0')* factor;
        }
    return value;
    }
    
char* extract(char* str, int& index)
    {
    char buffer[MAX];       //временное пространство для подстроки
    char* p_str = 0;        //указатель на новую строку для возврата
    int numL = 0;           //счетчик найденных левых скобок
    int buf_index = index;  //сохранить начальное значение index
    do
        {
        buffer[index - buf_index] = *(str+index); //копируем символ текущей строки в подстроку
        switch(buffer[index - buf_index]) //смотрим, чо это за символ
            {
            case ')':
                if (numL == 0)
                    {
                    buffer[index - buf_index] = '\0'; //если счетчик скобочек верный, ставим символ конца строки
                    ++index;    //устанавливаем индекс на следующий за скобочкой элемент
                    p_str = new char[index-buf_index];
                    if (!p_str)
                        {
                        cout << "Выделение памяти не удалось, программа прервана.";
                        exit(1);
                        }
                    strcpy_s(p_str, index - buf_index, buffer); //и копируем подстроку в новую память
                    return p_str;
                    }
                else
                    numL--;     //уменьшаем счетчик скобок
                break;
            case '(':
                numL++;         //соответственно увеличиваем
                break;
            }
        } while (*(str + index++) != '\0');     //устанавливаем индекс в следующий элемент
    cout << "Вывод за пределы выражения, возможно, плохой ввод." << endl;
    exit(1);
    return p_str;
    }
2
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru