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

Вычисление текстовой формулы - C++

Восстановить пароль Регистрация
 
Tmin100
 Аватар для Tmin100
6 / 6 / 0
Регистрация: 12.10.2012
Сообщений: 71
10.11.2012, 18:56     Вычисление текстовой формулы #1
Есть электронная таблица, в ячейке записано что то типа: =C1+AC234/A1.
Для вычисления такой формулы нужно для каждого адреса ячейки (C1, AC234, A1) вызвать метод таблицы calculate('C', 1), calculate('AC', 234), calculate('A', 1). Получить значение типа double и вставить в формулу. Потом всё это надо вычислить...

По первой части хочется спросить про аналог регулярных выражений, т.к. нужно выделить 1-5 символов и потом 1-5 цифр после них?
По второму я понимаю, что сначала нужно преобразовать строку к обратной польской записи и потом посчитать стеком, но нет ли уже реализованного алгоритма?

Добавлено через 14 минут
Пока только нашёл алгоритм по вычислению значения по обратной польской записи...
http://ru.wikiversity.org/wiki/Обрат...ы_реализации#C
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
igorrr37
 Аватар для igorrr37
1593 / 1221 / 118
Регистрация: 21.12.2010
Сообщений: 1,868
Записей в блоге: 7
10.11.2012, 20:40     Вычисление текстовой формулы #2
разделить можно через регекс
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <string>
#include <boost/regex.hpp>
 
int main()
{
    std::string s("=C1+AC234/A1");
    boost::regex reg("([A-Z]{1,5})([0-9]{1,5})");
    boost::regex_iterator<std::string::const_iterator> ib(s.cbegin(), s.cend(), reg), ie;
    for(; ib != ie; ++ib)
    {
        std::cout << (*ib)[1] << ' ' << (*ib)[2] << std::endl;
    }
    return 0;
}
Миниатюры
Вычисление текстовой формулы  
Tmin100
 Аватар для Tmin100
6 / 6 / 0
Регистрация: 12.10.2012
Сообщений: 71
10.11.2012, 21:01  [ТС]     Вычисление текстовой формулы #3
Так, это регулярные выражения из Boost.
В вики написано, что с 2011 года регулярные выражения включены в стандарт С++, ими можно воспользоваться сейчас?
igorrr37
 Аватар для igorrr37
1593 / 1221 / 118
Регистрация: 21.12.2010
Сообщений: 1,868
Записей в блоге: 7
10.11.2012, 22:34     Вычисление текстовой формулы #4
а попробуй такую штуку
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
#include <iostream>
#include <string>
#include <cctype>
#include <list>
#include <utility>
 
class Parser
{
public:
    Parser(){}
    void Parse(std::string const& s)
    {
        list.clear();
        let.clear();
        dig.clear();
        state = Base;
        for(std::string::const_iterator cib = s.begin(), cie = s.end(); cib != cie; ++cib)
        {
            if(isalpha(*cib) && isupper(*cib))
            {
                switch(state)
                {
                    case Dig:
                        Dump();
                        state = Base;
                        break;
                    default:
                        state = Let;
                        break;
                }
                Collect(*cib);
            }
            else if(isdigit(*cib))
            {
                if(Let == state)
                {
                    state = Dig;
                }
                Collect(*cib);
            }
            else
            {
                if(Dig == state)
                    Dump();
                state = Base;
            }
        }
        if(Dig == state)
            Dump();
    }
    typedef std::list<std::pair<std::string, std::string> >::const_iterator const_iterator;
    const_iterator begin() const
    {
        return list.cbegin();
    }
    const_iterator end() const
    {
        return list.cend();
    }
private:
    enum State{Base = 0, Let = 1, Dig = 2};
    State state;
    std::list<std::pair<std::string, std::string> > list;
    std::string let, dig;
    void Collect(char c)
    {
        if(isdigit(c))
            dig += c;
        else if(isalpha(c) && isupper(c))
            let += c;
    }
    void Dump()
    {
        list.push_back(std::make_pair(let, dig));
        let.clear();
        dig.clear();
    }
};
 
int main()
{
    Parser p;
    p.Parse("=C1+AC234/A1-C51");
    for(Parser::const_iterator ib = p.begin(), ie = p.end(); ib != ie; ++ib)
    {
        std::cout << ib->first << ' ' << ib->second << std::endl;
    }
    return 0;
}
Tmin100
 Аватар для Tmin100
6 / 6 / 0
Регистрация: 12.10.2012
Сообщений: 71
11.11.2012, 12:49  [ТС]     Вычисление текстовой формулы #5
2 ошибки:
В строке return list.cbegin();
main.cpp:54: ошибка: 'const class std::list<std::pair<std::basic_string<char>, std::basic_string<char> > >' has no member named 'cbegin'

В строке return list.cend();
main.cpp:58: ошибка: 'const class std::list<std::pair<std::basic_string<char>, std::basic_string<char> > >' has no member named 'cend'

Использую Qt-creator, Ubuntu 12.10

Добавлено через 8 минут
Почитал документацию, у list нет методов cend и cbegin, только rbegin и rend
igorrr37
 Аватар для igorrr37
1593 / 1221 / 118
Регистрация: 21.12.2010
Сообщений: 1,868
Записей в блоге: 7
12.11.2012, 15:42     Вычисление текстовой формулы #6
замени на begin() и end(), возможно сработает.
ОПН
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
#include <iostream>
#include <stack>
#include <cctype>
#include <map>
#include <sstream>
 
int main()
{
    std::string s("(22.9 + 27.1)* 4 / ((.55 + 99.45) / 2.0)"), srpn;
    std::string::size_type ind;
    while((ind = s.find(' ')) != std::string::npos) // удаление пробелов из входной строки
    {
        s.erase(ind, 1);
    }
    std::map<char, size_t> map; // карата весов символов
    map.insert(std::make_pair('*', 3));
    map.insert(std::make_pair('/', 3));
    map.insert(std::make_pair('+', 2));
    map.insert(std::make_pair('-', 2));
    map.insert(std::make_pair('(', 1));
    std::stack<char> stack;
    for(auto c : s) // формировка результирующей строки в ОПЗ
    {
        if(!isdigit(c) && ('.' != c))
        {
            srpn += ' ';
            if(')' == c)
            {
                while(stack.top() != '(')
                {
                    srpn += stack.top();
                    stack.pop();
                    srpn += ' ';
                }
                stack.pop();
            }
            else if('(' == c)
            {
                stack.push(c);
            }
            else if(stack.empty() || (map[stack.top()] < map[c]))
            {
                stack.push(c);
            }
            else
            {
                do
                {
                    srpn += stack.top();
                    srpn += ' ';
                    stack.pop();
                }
                while(!(stack.empty() || (map[stack.top()] < map[c])));
                stack.push(c);
            }
        }
        else
        {
            srpn += c;
        }
    }
    while(!stack.empty())// остаток из стека добавляется в результ. строку
    {
        srpn += stack.top();
        srpn += ' ';
        stack.pop();
    }
    std::cout << srpn << std::endl; // результирующая строка в ОПЗ
    std::stack<double> dstack;
    std::stringstream ss(srpn);
    double d, d1;
    char c;
    while(ss.get(c)) // вычисление результата
    {
        if(isdigit(c) || '.' == c)
        {
            ss.unget();
            ss >> d;
            dstack.push(d);
        }
        else if(!isspace(c))
        {
            d1 = dstack.top();
            dstack.pop();
            d = dstack.top();
            dstack.pop();
            switch(c)
            {
                case '+':
                    dstack.push(d + d1);
                    break;
                case '-':
                    dstack.push(d - d1);
                    break;
                case '*':
                    dstack.push(d * d1);
                    break;
                case '/':
                    dstack.push(d / d1);
                    break;
            }
        }
    }
    if(!dstack.empty())
    {
        std::cout << dstack.top() << std::endl; // результат
        dstack.pop();
    }
    return 0;
}
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
17.11.2012, 19:59     Вычисление текстовой формулы
Еще ссылки по теме:

C++ Оптимизировать вычисление формулы
C++ Помогите найти ошибку в программе. Вычисление формулы.

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Tmin100
 Аватар для Tmin100
6 / 6 / 0
Регистрация: 12.10.2012
Сообщений: 71
17.11.2012, 19:59  [ТС]     Вычисление текстовой формулы #7
В итоге сделал валидацию так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bool valid(string str)
{
    bool chars=true;
    if(!isalpha(str[0])) //Если первый элемент не буква
        return false;
    for (int i=1; i<str.length(); i++)
    {
        if(isdigit(str[i])&&chars) //если элемент число, переключим
        {
            chars=false;
        }
        if (isalpha(str[i])&&!chars)
        {
            return false;
        }
    }
    return true;
}
Yandex
Объявления
17.11.2012, 19:59     Вычисление текстовой формулы
Ответ Создать тему
Опции темы

Текущее время: 12:23. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru