Форум программистов, компьютерный форум, киберфорум
Наши страницы
Обо всем!
Войти
Регистрация
Восстановить пароль
 
Etyuhibosecyu
Его Правительские Звания
-30 / 7 / 4
Регистрация: 13.07.2017
Сообщений: 502
Завершенные тесты: 1
1

Тест на знание C++

18.09.2018, 14:01. Просмотров 352. Ответов 6
Метки нет (Все метки)

Господин Usaga, у меня есть идея. Предлагаю оценить мои знания C++ в деле. Дайте мне какое-нибудь задание, которое сами можете выполнить за несколько часов, и я также попробую его выполнить. Только без редко используемых элементов языка и не по узкоспециализированной области. Стандартный встроенный в этот форум тест я уже проходил, и там большинство вопросов именно на редко используемые темы или из узкоспециализированных областей (из тех, что я помню - про cast-операторы или ++a--). Также попрошу, чтобы в этом задании не было работы с сетями. И это не потому, что я умышленно не желаю изучать эту тему, а потому, что я не смогу протестировать корректность выполнения такого задания - хоть два ноутбука у меня и есть (и то от одного - остатки), но двух подключений к сети с ноутбука - нет. Ну, как вам такая идея?
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.09.2018, 14:01
Ответы с готовыми решениями:

Внутренний диалог и чистое знание
Хочу не сколько задать вопрос, сколько высказать мнение и услышать другие точки зрения. Речь вот о...

Проект База знание для С# или С++
Здравствуйте я обращаюсь ко всем интересуюшимся, почему бы не создать базу знаний на С++ или на C# ...

Насколько важно знание C# в наше время
Привет форумчане! Скажите пожалуйста, хотя понятно, что тут сидят ярые любители этого языка,...

Рассылка писем, Тест на реакцию, Реакция тест, Рассылка писем, Тест на реакцию, как сделать
Как это сделать? Необходимо отправить сообщение по электронной почте списку адресатов, с...

Тест на знание Windows
Разработка гипертекстового документа "Тест на знание Windows"

6
Usaga
Эксперт .NET
5732 / 3962 / 707
Регистрация: 21.01.2016
Сообщений: 15,568
Завершенные тесты: 2
18.09.2018, 14:57 2
Etyuhibosecyu, я специализируюсь на C#. Попросите кого-нибудь из той ветки.

Но я не вижу смысла ваши знания проверять. Вы уже всё и так хорошо показали в своей длинной теме по DCASWTF. Лучше купите\качните учебник по языку и спокойно читайте, по ходу дела практикуясь на простых консольных проектах. Паясничать не надо. Как не надо и пытаться сразу сворачивать горы. У вас не получится, а времени уйдёт много.

Добавлено через 9 минут
Etyuhibosecyu, вы могли бы не отходить от кассы и попробовать реализовать разбор и вычисление простых арифметических выражений вида 5 + (45 *4) / 7 - 1. На вход строка, на выходе результат. Конечно же, пробелы и табуляции не должны мешать.

Сможете? Вы же всё равно транслятор пишете, у вас такое уже даже написанное где-то должно быть. Только код выкладывайте не в арихиве, а прямо сюда или сслыкой на GITHUB.
0
Etyuhibosecyu
Его Правительские Звания
-30 / 7 / 4
Регистрация: 13.07.2017
Сообщений: 502
Завершенные тесты: 1
18.09.2018, 18:34  [ТС] 3
Думаю, что сделал. И от того, на что указывал Rius про DCASTFPart1, программа не падает, и деление на ноль обрабатывает корректно - возвращает ноль. Завтра с утра войду с компьютера, выложу.
0
Etyuhibosecyu
Его Правительские Звания
-30 / 7 / 4
Регистрация: 13.07.2017
Сообщений: 502
Завершенные тесты: 1
19.09.2018, 09:27  [ТС] 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
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
//ArithExprs.cpp
// ArithExprs.cpp : Этот файл содержит функцию "main". Здесь начинается и заканчивается выполнение программы.
 
#include "pch.h"//Что это за файл и для чего он нужен, я не знаю, но если удалить эту строку, выпрыгивает ошибка
#include "ArithExprs.h"
 
int main() {
    std::string s = "";
    char c;
    while (1 == 1) {
        c = std::cin.get();
        if (c == '\n') {
            if (s == "") {
                return 0;
            }
            std::cout << "=" << ArithExprs::parse(s) << std::endl;
            s = "";
        }
        else {
            s += c;
        }
    }
    return 0;
}
//ArithExprs.h
#pragma once
#include <iostream>
#include <string>
#include <limits>
 
std::string operators[4] = { "+", "-", "*", "/" };
 
class ArithExprs {
public:
    static double parse(std::string expression) {
        std::string e = trim(expression);
        if (is_numeric(e) == true) {
            return atof(e.c_str());
        }
        for (int i = 0; i <= 3; i++) {
            size_t find_start = e.length();
            while (1 == 1) {
                size_t t = e.rfind(operators[i], find_start);
                if (t != e.npos) {
                    if (t == 0) {
                        if (i == 0 || i == 1) {
                            return parse_operator(0, i, parse(e.substr(t + 1, e.length() - t - 1)));
                        }
                        else {
                            return 0;
                        }
                    }
                    else if (((e.find_last_of("+-*/Ee", t - 1) > e.find_last_of("1234567890", t - 1) || e.find_last_of("1234567890", t - 1) == e.npos) && e.find_last_of("+-*/Ee", t - 1) != e.npos) || string_count(e.substr(t + 1, e.length() - t - 1), ")") > string_count(e.substr(t + 1, e.length() - t - 1), "(")) {
                        find_start = t - 1;
                        continue;
                    }
                    else {
                        return parse_operator(parse(e.substr(0, t)), i, parse(e.substr(t + 1, e.length() - t - 1)));
                    }
                }
                else {
                    break;
                }
            }
        }
        if (e[0] == '(' && e[e.length() - 1] == ')') {
            return parse(e.substr(1, e.length() - 2));
        }
        return 0;
    }
 
    static double parse_operator(double x, int operator_index, double y) {
        switch (operator_index) {
        case 0: return x + y;
        case 1: return x - y;
        case 2: return x * y;
        case 3:
            if (y == 0) {
                return 0;
            }
            else {
                return x / y;
            }
        default: return 0;
        }
    }
 
    static bool is_numeric(std::string string, bool forbid_exponent = false, bool only_digits = false, double max = -1) {
        if (only_digits == false) {
            if (forbid_exponent == false) {
                std::string s = replace(string, "e", "E");
                if (s.find("E+") != s.npos) {
                    return (is_numeric(get_before(s, "E+"), true, false, 9.999999999999) && is_numeric(get_after(s, "E+"), true, true, 307)) || (is_numeric(get_before(s, "E+"), true, false, 1.797693134862) && is_numeric(get_after(s, "E+"), true, true, 308));
                }
                else if (s.find("E-") != s.npos) {
                    return is_numeric(get_before(s, "E-"), true) && is_numeric(get_after(s, "E-"), true, true);
                }
            }
            bool m = false, p = false;
            for (int i = 0; i <= (int)string.length() - 1; i++) {
                if (string[i] == '+' || string[i] == '-') {
                    if (i == 0) {
                        m = true;
                    }
                    else {
                        return false;
                    }
                }
                else if (string[i] == '.') {
                    if (i != 0 && !(i == 1 && m == true)) {
                        p = true;
                    }
                    else {
                        return false;
                    }
                }
                else if ((int)string[i] < (int)'0' || (int)string[i] > (int)'9') {
                    return false;
                }
            }
            std::string s;
            if (m == true) {
                s = string.substr(1, string.length() - 1);
            }
            else {
                s = string;
            }
            return (atof(replace(s, ".", ",").c_str()) <= max || max < 0);
        }
        else {
            for (int i = 0; i <= (int)string.length() - 1; i++) {
                if ((int)string[i] < (int)'0' || (int)string[i] > (int)'9') {
                    return false;
                }
            }
            return (atof(string.c_str()) <= max || max < 0);
        }
    }
 
    static std::string replace(std::string string, const std::string old_string, const std::string new_string) {
        std::string s = string;
        size_t i = 0;
        while ((i = s.find(old_string, i)) != s.npos) {
            s = s.replace(i, old_string.length(), new_string);
            i += new_string.length();
        }
        return s;
    }
 
    static long int string_count(std::string str, std::string substr, size_t _Off = 0U) {
        long int t = 0;
        std::string s;
        if (str.find(substr, _Off) == str.npos) {
            return 0;
        }
        s = str.substr(str.find(substr, _Off) + substr.length(), str.length() - str.find(substr, _Off) - substr.length());
        t = 1;
        while (s.find(substr) != s.npos) {
            s = get_after(s, substr);
            t++;
        }
        return t;
    }
 
    static std::string get_before(std::string str, std::string substr) {
        if (str.find(substr) == str.npos) {
            return str;
        }
        else {
            return str.substr(0, str.find(substr));
        }
    }
 
    static std::string get_after(std::string str, std::string substr) {
        if (str.find(substr) == str.npos) {
            return "";
        }
        else {
            return str.substr(str.find(substr) + substr.length(), str.length() - str.find(substr) - substr.length());
        }
    }
 
    static std::string trim(std::string str) {
        return rtrim(ltrim(str));
    }
 
    static std::string rtrim(std::string str) {
        if (str == "") {
            return "";
        }
        std::string a = str;
        while (a[a.length() - 1] == ' ' || a[a.length() - 1] == '\t' || a[a.length() - 1] == (char)13 || a[a.length() - 1] == (char)10 || a[a.length() - 1] == (char)160) {
            //13 - перевод строки, 10 - точно не знаю что, но тоже используется при переводе строки, 160 - неразрывный пробел
            a = a.substr(0, a.length() - 1);
        }
        return a;
    }
 
    static std::string ltrim(std::string str) {
        if (str == "") {
            return "";
        }
        std::string a = str;
        while (a[0] == ' ' || a[0] == '\t' || a[0] == (char)13 || a[0] == (char)10 || a[0] == (char)160) {
            a = a.substr(1, a.length() - 1);
        }
        return a;
    }
};
0
Usaga
Эксперт .NET
5732 / 3962 / 707
Регистрация: 21.01.2016
Сообщений: 15,568
Завершенные тесты: 2
19.09.2018, 10:10 5
Etyuhibosecyu, ну вот примерно такого я и ожидал)

Но хоть код причёсанный.

"pch.h" - precompiled header. Погуглите для чего оно. Я в подробностях не расскажу.

Принимать входную строку посимвольно и формировать строку КОНКАТЕНАЦИЕЙ - фу лютое. В stdlibc++ должна быть функция приёма сразу целой строки в виде std::string.

Лексемы из входной строки нужно вычитывать с помощью конечного автомата, а не кучки trim() + rfind(). Это очень грязное и хрупкое решение. И неэффективное.

И вычислять это дело походу разбора - жуть какая кривота. Нужно разбирая строку, строить дерево выражения, которое и вычислять уже по окончанию его формирования.

Если вы и транслятор свой в таком же духе делаете, то ваша задумка затянется на многие годы)

Подобные вещи, что разбор формулы, что кода исходного, делаются через трансляцию в некое внутреннее представление (Expression Tree, AST - Abstract Syntax Tree), которое уже потом и вычисляется\компилируется\транслируется.

Т.е. так: исходная строка(или целый файл) -> внутреннее представление -> обработка.

Загуглите такие вещи (они непосредственно нужны для вашего решения): конечный автомат, дерево выражений, абстрактное синтаксическое дерево.

Код, что вы тут представили чистый, но само решение отвратное. Изучите вещи, что я выше обозначил и попробуйте переписать. Затратьте времени столько, сколько будет нужно.

Добавлено через 17 минут
И да, у вас тут строки везде по значению передаются, тоже так себе. Передавайте по ссылке, не надо 100500 раз строки копировать, это неэффективно.
0
Etyuhibosecyu
Его Правительские Звания
-30 / 7 / 4
Регистрация: 13.07.2017
Сообщений: 502
Завершенные тесты: 1
19.09.2018, 20:48  [ТС] 6
Цитата Сообщение от Usaga Посмотреть сообщение
Принимать входную строку посимвольно и формировать строку КОНКАТЕНАЦИЕЙ - фу лютое.
Я знаю, std::cin >> string;. Но эта конструкция считывает до первого пробела или табуляции, а совсем не всю строку.
Цитата Сообщение от Usaga Посмотреть сообщение
Лексемы из входной строки нужно вычитывать с помощью конечного автомата, а не кучки trim() + rfind().
Про конечные автоматы читал и в Википедии, и на других сайтах, но как с их помощью вычитывать лексемы, так и не понял.
Цитата Сообщение от Usaga Посмотреть сообщение
И вычислять это дело походу разбора - жуть какая кривота. Нужно разбирая строку, строить дерево выражения, которое и вычислять уже по окончанию его формирования.
Исправил. Хотя у этого дерева есть большой недостаток - память выделяется одновременно как для числа, так и для подвыражений. Я уже и на форуме спрашивал, как этого избежать, написали, что с помощью union, но у меня ничего не получилось. В разборе языка для этого, конечно, потребовалось бы гигантское количество памяти.
Цитата Сообщение от Usaga Посмотреть сообщение
Если вы и транслятор свой в таком же духе делаете, то ваша задумка затянется на многие годы)
Не согласен. Вычислять походу разбора - проще, быстрее и требует меньше памяти.
Цитата Сообщение от Usaga Посмотреть сообщение
И да, у вас тут строки везде по значению передаются, тоже так себе. Передавайте по ссылке, не надо 100500 раз строки копировать, это неэффективно.
Исправил.
В целом, вижу, что знания у меня не блестящие. Но я иду по простому пути, который требует минимум обучения. Хотя, возможно, он не всегда рациональный.
В общем, код такой:
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
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
//ArithExprs.cpp
// ArithExprs.cpp : Этот файл содержит функцию "main". Здесь начинается и заканчивается выполнение программы.
 
#include "pch.h"//Что это за файл и для чего он нужен, я не знаю, но если удалить эту строку, выпрыгивает ошибка
#include "ArithExprs.h"
 
int main() {
    std::string s = "";
    char c;
    while (1 == 1) {
        c = std::cin.get();
        if (c == '\n') {
            if (s == "") {
                return 0;
            }
            std::cout << "=" << ArithExprs::parse(s) << std::endl;
            s = "";
        }
        else {
            s += c;
        }
    }
    return 0;
}
//ArithExprs.h
#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <limits>
 
std::string operators[4] = { "+", "-", "*", "/" };
 
class Expression {
public:
    enum Expression_type {
        single,
        unary,
        binary,
    };
 
    Expression_type type = single;
    double number = 0;
    Expression *x = nullptr;
    int operator_index = 0;
    Expression *y = nullptr;
 
    Expression() {}
 
    Expression(double new_number) {
        type = single;
        number = new_number;
    }
 
    Expression(int new_operator_index, const Expression &new_y) {
        type = unary;
        operator_index = new_operator_index;
        y = new Expression(new_y);
    }
 
    Expression(const Expression &new_x, int new_operator_index, const Expression &new_y) {
        type = binary;
        x = new Expression(new_x);
        operator_index = new_operator_index;
        y = new Expression(new_y);
    }
 
    operator double() {
        if (type == single) {
            return number;
        }
        else if (type == unary) {
            switch (operator_index) {
            case 0: return *y;
            case 1: return -*y;
            default: return 0;
            }
        }
        else {
            switch (operator_index) {
            case 0: return *x + *y;
            case 1: return *x - *y;
            case 2: return *x * *y;
            case 3:
                if (*y == 0) {
                    return 0;
                }
                else {
                    return *x / *y;
                }
            default: return 0;
            }
        }
    }
};
 
 
class ArithExprs {
public:
    static Expression parse(const std::string &expression) {
        std::string e = trim(expression);
        if (is_numeric(e) == true) {
            return atof(e.c_str());
        }
        for (int i = 0; i <= 3; i++) {
            size_t find_start = e.length();
            while (1 == 1) {
                size_t t = e.rfind(operators[i], find_start);
                if (t != e.npos) {
                    if (t == 0) {
                        if (i == 0 || i == 1) {
                            return Expression(i, parse(e.substr(t + 1, e.length() - t - 1)));
                        }
                        else {
                            return 0;
                        }
                    }
                    else if (((e.find_last_of("+-*/Ee", t - 1) > e.find_last_of("1234567890", t - 1) || e.find_last_of("1234567890", t - 1) == e.npos) && e.find_last_of("+-*/Ee", t - 1) != e.npos) || string_count(e.substr(t + 1, e.length() - t - 1), ")") > string_count(e.substr(t + 1, e.length() - t - 1), "(")) {
                        find_start = t - 1;
                        continue;
                    }
                    else {
                        return Expression(parse(e.substr(0, t)), i, parse(e.substr(t + 1, e.length() - t - 1)));
                    }
                }
                else {
                    break;
                }
            }
        }
        if (e[0] == '(' && e[e.length() - 1] == ')') {
            return parse(e.substr(1, e.length() - 2));
        }
        return 0;
    }
 
    static bool is_numeric(const std::string &string, bool forbid_exponent = false, bool only_digits = false, double max = -1) {
        if (only_digits == false) {
            if (forbid_exponent == false) {
                std::string s = replace(string, "e", "E");
                if (s.find("E+") != s.npos) {
                    return (is_numeric(get_before(s, "E+"), true, false, 9.999999999999) && is_numeric(get_after(s, "E+"), true, true, 307)) || (is_numeric(get_before(s, "E+"), true, false, 1.797693134862) && is_numeric(get_after(s, "E+"), true, true, 308));
                }
                else if (s.find("E-") != s.npos) {
                    return is_numeric(get_before(s, "E-"), true) && is_numeric(get_after(s, "E-"), true, true);
                }
            }
            bool m = false, p = false;
            for (int i = 0; i <= (int)string.length() - 1; i++) {
                if (string[i] == '+' || string[i] == '-') {
                    if (i == 0) {
                        m = true;
                    }
                    else {
                        return false;
                    }
                }
                else if (string[i] == '.') {
                    if (i != 0 && !(i == 1 && m == true)) {
                        p = true;
                    }
                    else {
                        return false;
                    }
                }
                else if ((int)string[i] < (int)'0' || (int)string[i] > (int)'9') {
                    return false;
                }
            }
            std::string s;
            if (m == true) {
                s = string.substr(1, string.length() - 1);
            }
            else {
                s = string;
            }
            return (atof(replace(s, ".", ",").c_str()) <= max || max < 0);
        }
        else {
            for (int i = 0; i <= (int)string.length() - 1; i++) {
                if ((int)string[i] < (int)'0' || (int)string[i] > (int)'9') {
                    return false;
                }
            }
            return (atof(string.c_str()) <= max || max < 0);
        }
    }
 
    static std::string replace(const std::string &string, const std::string &old_string, const std::string &new_string) {
        std::string s = string;
        size_t i = 0;
        while ((i = s.find(old_string, i)) != s.npos) {
            s = s.replace(i, old_string.length(), new_string);
            i += new_string.length();
        }
        return s;
    }
 
    static long int string_count(const std::string &str, const std::string &substr, size_t _Off = 0U) {
        long int t = 0;
        std::string s;
        if (str.find(substr, _Off) == str.npos) {
            return 0;
        }
        s = str.substr(str.find(substr, _Off) + substr.length(), str.length() - str.find(substr, _Off) - substr.length());
        t = 1;
        while (s.find(substr) != s.npos) {
            s = get_after(s, substr);
            t++;
        }
        return t;
    }
 
    static std::string get_before(const std::string &str, const std::string &substr) {
        if (str.find(substr) == str.npos) {
            return str;
        }
        else {
            return str.substr(0, str.find(substr));
        }
    }
 
    static std::string get_after(const std::string &str, const std::string &substr) {
        if (str.find(substr) == str.npos) {
            return "";
        }
        else {
            return str.substr(str.find(substr) + substr.length(), str.length() - str.find(substr) - substr.length());
        }
    }
 
    static std::string trim(const std::string &str) {
        return rtrim(ltrim(str));
    }
 
    static std::string rtrim(const std::string &str) {
        if (str == "") {
            return "";
        }
        std::string a = str;
        while (a[a.length() - 1] == ' ' || a[a.length() - 1] == '\t' || a[a.length() - 1] == (char)13 || a[a.length() - 1] == (char)10 || a[a.length() - 1] == (char)160) {
            //13 - перевод строки, 10 - точно не знаю что, но тоже используется при переводе строки, 160 - неразрывный пробел
            a = a.substr(0, a.length() - 1);
        }
        return a;
    }
 
    static std::string ltrim(const std::string &str) {
        if (str == "") {
            return "";
        }
        std::string a = str;
        while (a[0] == ' ' || a[0] == '\t' || a[0] == (char)13 || a[0] == (char)10 || a[0] == (char)160) {
            a = a.substr(1, a.length() - 1);
        }
        return a;
    }
};
P. S. Вы украинец?

Добавлено через 38 минут
Еще напишу, как реализовался бы класс Expression в DCASTF++:
Код
Базблок : Блок Выражение
//Базблок - сокращение от "Базовый блок", блок, в котором
//определены конструктор по всем величинам, операторы
//действий над первыми числовой, строковой и логической
//величинами, операторы = и <>/!=/нр и т. д.
	Перечис Тип выражения
		тЧисло
		Унарное
		Бинарное
	Конец перечис

	Тип выражения : Тип = тЧисло
	1 //Это звезда
	УСЛОВИЕ Тип=тЧисло
		В области 1
		Число : Число = 0
		Конец области
	ПОДУСЛОВИЕ Тип=Унарное
		В области 1
		Целое : Номер оператора = 0
		Выражение : А = 0
		Конец области
	В остальных случаях
		В области 1
		Выражение : А = 0
		Целое : Номер оператора = 0
		Выражение : Б = 0
		Конец области
	Конец условия

	Конструктор(Число : нЧисло)
		Тип = тЧисло
		Число = нЧисло

	Конструктор(Целое : нНомер оператора, Выражение : нА)
		Тип = Унарное
		Номер оператора = нНомер оператора
		А = нА

	Конструктор(Выражение : нА, Целое : нНомер оператора, Выражение : нБ)
		Тип = Бинарное
		А = нА
		Номер оператора = нНомер оператора
		Б = нБ

	Преобразование в Число()
		//Здесь я не буду ничего писать, так как ничего особенного в этом нет
Это предварительный код, он может еще очень много раз поменяться. Суть в том, что создаются только те величины, которые нужны для данного конструктора. Если вдруг так случится, что пользователь обратится к величине, которой не существует, это обращение просто вернет пустоту.
0
Usaga
Эксперт .NET
5732 / 3962 / 707
Регистрация: 21.01.2016
Сообщений: 15,568
Завершенные тесты: 2
20.09.2018, 06:03 7
Цитата Сообщение от Etyuhibosecyu Посмотреть сообщение
Я знаю, std::cin >> string;. Но эта конструкция считывает до первого пробела или табуляции, а совсем не всю строку.
Гугл говорит, что есть такой метод:

C++
1
2
std::string str;
std::getline(std::cin, str);
Цитата Сообщение от Etyuhibosecyu Посмотреть сообщение
Про конечные автоматы читал и в Википедии, и на других сайтах, но как с их помощью вычитывать лексемы, так и не понял.
Речь о объекте с состоянием, который для каждого входящего символа выбирает алгоритм обработки опираясь на это самое состояние. Простой автомат для подсчёта слов в строке (на C#):
Кликните здесь для просмотра всего текста
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
    class myClass
    {
        enum WordCountState
        {
            Init,
            Word,
            WhiteSpace
        }
 
        static int CountWords(string originString)
        {
            int wordCounter = 0;
            WordCountState state = WordCountState.Init;
 
            foreach (Char c in originString) {
                // In case of whitespace
                if (Char.IsWhiteSpace(c)) {
                    switch (state) {
                        case WordCountState.Init:
                        case WordCountState.Word:
                            state = WordCountState.WhiteSpace;
                            break;
                    }
                // In case of non-whitespace char
                } else {
                    switch (state) {
                        case WordCountState.Init:
                        case WordCountState.WhiteSpace:
                            // Incerement out counter if we met non-whitespace
                            // char after whitespace (one or more)
                            wordCounter++;
                            state = WordCountState.Word;
                            break;
                    }
                }
            }
 
            return wordCounter;
        }


С помощью такого автомата можно просто выделять слова в строке игнорируя пробелы. А если усложнить, то можно научить выделять именно языковые лексемы, а не просто слова.

Цитата Сообщение от Etyuhibosecyu Посмотреть сообщение
Хотя у этого дерева есть большой недостаток - память выделяется одновременно как для числа, так и для подвыражений.
Это уже недостаток вашего решения. Операнды могут быть разными, под них нужно выделять память, ничего в этом страшного. Но множество операторов ограниченно. Их можно сделать статическими и переиспользовать. Ссылку на один и тот же оператор "+" можно пихать 100500 раз подряд в разные узлы дерева. У этого оператора нет состояния, его можно переиспользовать.

Цитата Сообщение от Etyuhibosecyu Посмотреть сообщение
Не согласен. Вычислять походу разбора - проще, быстрее и требует меньше памяти.
Нет, это полная фигня и ни разу не проще. У вас каша из строк, логики их разбора и вычислений. А так разбор отдельно, модель выражения - отдельно, проход по дереву этого выражения - отдельно. Памяти под саму модель выражения (дерево) уходит копейки. Взамен же чистота и ясность модели.

Цитата Сообщение от Etyuhibosecyu Посмотреть сообщение
Исправил.
Нет, всё та же хрень. Разбирайте строку автоматом, а не тримами и рфайндами. Стройте ДЕРЕВО выражения, узлами которого являются объекты операторов и операндов. И вычисляйте это выражение уже в самом конце, когда оно построено.

И что это за дичь такая?
C++
1
2
3
4
5
6
    static std::string ltrim(const std::string &str) {
 
        std::string a = str; // Какого чёрта?
 
        return a;
    }
Цитата Сообщение от Etyuhibosecyu Посмотреть сообщение
P. S. Вы украинец?
Нет. Я просто не люблю говнокод.

Цитата Сообщение от Etyuhibosecyu Посмотреть сообщение
Еще напишу, как реализовался бы класс Expression в DCASTF++:
Хрень. Модель выражения - отдельный объект с деревом внутри. Операторы и операнды - отдельные объекты. Нужна полная декомпозиция этой каши на отдельные объекты. Тогда всё разложится на отдельные специализированные и чистые вещи: выражение, его вычисление, элементы выражения. И такая модель будет надёжной и расширяемой.
0
20.09.2018, 06:03
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.09.2018, 06:03

Тест на знание Delphi
На знание Delphi то есть мне нужны просто готовые вопросы с ответами чтобы вставить в компонент...

Тест на знание ассемблера
Доброго времени суток, господа! В этом семестре нам преподавали системное программирование. Я...

Тест на знание работы компилятора
Привет, начал проходить курс по С++, и тут ступор. Нужно выбрать буквы верных утверждений : а)...


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru