![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| ТарасАтавин |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 370 Регистрация: 26.8.2013 Репутация: нет Всего: нет |
Дан приблизительно вот такой: "<tab>1552</tab><variable>y</variable><LeftAssigneOperator><fraction><numerator><function>sin</function>(<variable>x</variable>)</numerator><denominator><function>cos</function>(<variable>x</variable>)+<fraction><numerator>3</numerator><denominator>2</denominator></fraction></denominator></fraction>" код формулы. Здесь <tab></tab> - тег табуляции в пикселах, <LeftAssigneOperator> - тег стрелки влево (вместо знака равенства), а всё остальное - xml код правой части. <fraction></fraction> - тег дроби, <numerator></numerator> - тег числителя, <denominator></denominator> - тег знаменателя, <function></function> - тег идентификатора функции, а <variable></variable> - тег идентификатора переменной. Не дробные члены выражения вне дроби следует разместить посередине между строками числителя и знаменателя. Ниже и выше могут быть другие строки. Пока дробь двухэтажная, проблем нет, но как только в числителе, или знаменателе тоже есть дроби, то соседние строки налазят на них. Как оценить количество этажей дроби и отдельно её числителя и знаменателя и как в связи с этим выставить вертикальные смещения фрагментов формулы?
Это сообщение отредактировал(а) ТарасАтавин - 30.8.2013, 09:19 -------------------- Не так всё плохо, как оно есть на самом деле. |
|||
|
||||
| ТарасАтавин |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 370 Регистрация: 26.8.2013 Репутация: нет Всего: нет |
-------------------- Не так всё плохо, как оно есть на самом деле. |
|||
|
||||
| ТарасАтавин |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 370 Регистрация: 26.8.2013 Репутация: нет Всего: нет |
Проблема дроби в знаменателе была в том, что сбивала высота номера, выводимого после самой строки. А вот если эта же строка закодирована так: "<tab>1552</tab><variable>y</variable><LeftAssigneOperator><fraction><numerator><function>sin</function>(<variable>x</variable>)+<fraction><numerator>3</numerator><denominator>2</denominator></fraction></numerator><denominator><function>cos</function>(<variable>x</variable>)</denominator></fraction>", то получается
![]() вместо ![]() . И здесь проблема именно в высоте числителя. Как её заранее оценить до начала вывода выражения и как обработать? Это сообщение отредактировал(а) ТарасАтавин - 30.8.2013, 10:29 -------------------- Не так всё плохо, как оно есть на самом деле. |
|||
|
||||
| akizelokro |
|
|||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
Делай класс "Выражение" вида
class Expression { .... bool _fraction; // флаг, дробь или выражение в строку bool isFraction() {retrun _fraction; }; Expression * numerator; // что в числителе // аналогично для знаменателя, указатель на выражение. в случае если выражение не дробь оба эти указателя NULL long getHeight() { int numeratorHeight = 0; if(numerator) numeratorHeight = numerator->getHeight(); // рекурсия, о которой ты вчера упоминал. и заодно сделаешь код, который можно будет потом юзать много раз ..... дальше если ссылка на знаменатель не NULL а дальше либо суммируешь высоты для числителя и знаменателя, либо если вообще не дробь, вычисляешь просто высоту выражения } } сначала парсишь выражение, если дробь, по идёшь парсить по дереву перебора, пока не дойдёшь до конца. создаёшь все нужные экземпляры класа Expression, дальше их юзаешь можешь всё это сделать и через функции без классов, но в коде погрязнешь просто. В смысле, дроби у тебя могут быть и "многоэтажные", мой подход это учитывает. Это сообщение отредактировал(а) akizelokro - 30.8.2013, 11:11 -------------------- a = a + b; b = a - b; a = a - b; |
|||
|
||||
| akizelokro |
|
|||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
И лучше вообще СSize выдавать, а не отдельно высоту
-------------------- a = a + b; b = a - b; a = a - b; |
|||
|
||||
| ТарасАтавин |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 370 Регистрация: 26.8.2013 Репутация: нет Всего: нет |
Ничего не понял.
-------------------- Не так всё плохо, как оно есть на самом деле. |
|||
|
||||
| akizelokro |
|
|||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
Что тут непонятного? В числителе и знаменателе могут быть в свою очередь дроби. Значит, вопрос свести математическое выражение не к последней по счёту элементарной дроби, а к однострочному выражению, которое, к тому же, может быть частью дроби.( А может и не быть.) То есть задача такая, чтобы найти такую модель построения классов выражений, чтобы всё хорошо описывалось. Представим, что дробь - однострочный объект, но разделённый на два "этажа", числитель и знаменатель. Которые в свою очередь однострочные объекты и могут быть дробями в свою очередь, по нашей терминологии однострочными объектами, разделенными на два этажа. Ферштеен? Абстрагируешься от того, что числитель и знаменатель это строки, рассматриваешь их как этажи. Сама дробь - это, к примеру дом, а знаменатель - первый этаж, числитель второй этаж. Дальше предполагаешь что, числитель не просто этаж, а ещё и дом, в котором тоже может быть два этажа. И так далее, хоть до бесконечности. То есть, тебе в самом первом объекте дома нужен логический флаг, определяющий, что "дом" это не просто "дом", а двухэтажный дом. И адреса-номера этажей, в моей модели это указатели на объекты. (Если этажей нет, то указатели равны NULL)/ Модель вложенных поэтажно друг в друга двухэтажных домов. Добавлено @ 12:06 В принципе, так можно построить и многомерные аналоги дробей. Чего уж мелочиться? Это сообщение отредактировал(а) akizelokro - 30.8.2013, 12:07 -------------------- a = a + b; b = a - b; a = a - b; |
|||
|
||||
| ТарасАтавин |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 370 Регистрация: 26.8.2013 Репутация: нет Всего: нет |
1. Ну и как это будет выглядеть? 2. Что оно будет значить? Допустим. А какова здесь роль класса? -------------------- Не так всё плохо, как оно есть на самом деле. |
|||
|
||||
| ТарасАтавин |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 370 Регистрация: 26.8.2013 Репутация: нет Всего: нет |
Проблема решена рекурсивными функциями:
-------------------- Не так всё плохо, как оно есть на самом деле. |
|||
|
||||
| akizelokro |
|
|||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
Роль класса здесь свелась бы к элементарному упорядочиванию. .и развитию на перспективу. Потому что в класс можно было бы не только навесить метод определения выражения, но и другие полезные методы. Например, рисование части дроби. Также, класс бы дал хорошую возможность не слишком загружать код при увеличении "уровней дроби" или сложности выражения. На простом примере, степень в подстроке, в которую возводится частичная дробь. или корень Квадратный. А то и интеграл. -------------------- a = a + b; b = a - b; a = a - b; |
|||
|
||||
| ТарасАтавин |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 370 Регистрация: 26.8.2013 Репутация: нет Всего: нет |
Степень здесь не уместна из-за неоднозначности поведения в области отрицательных чисел, что оставляет функцию в качестве единственно допустимого обозначения степени. Корень - та же степень. А нижний индекс будет. Но я не вижу препятствий против его реализации в процедурной парадигме. Зато они отлично видны именно в объектной.
-------------------- Не так всё плохо, как оно есть на самом деле. |
|||
|
||||
| akizelokro |
|
|||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
Времени бы ушло примерно одинаково. Зато с классами можно делать задел для будущего. Раз ты уж сразу не захотел использовать никакую библиотеку. Получается, что ты вместо возможности сделать хороший задел для чего-то большего, ограничился меньшим. Хотя затраты времени были те же самые. -------------------- a = a + b; b = a - b; a = a - b; |
|||
|
||||
| ТарасАтавин |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 370 Регистрация: 26.8.2013 Репутация: нет Всего: нет |
Я делаю сразу то самое большое без задела на переделку. Все ограничения логичны и естественны. Та же степень. Обозначить её верхним индексом можно только одним способом, функции покрывают всё разнообразие степеней. А как степень с действительным показателем должна вести себя при отрицательном основании? Не так уж это однозначно. Поэтому функция. Нижний же индекс в значении "индекс элемента массива" ни чем таким не страдает. А вот с классами будет или супер ограничение "в правой части только дроби и ни каких операций", или сотни рефакторингов с топтанием на месте, потому что они здесь ни чего полезного не добавляют к тому, что проще делается в процедурной парадигме. Это сообщение отредактировал(а) ТарасАтавин - 3.9.2013, 06:09 -------------------- Не так всё плохо, как оно есть на самом деле. |
|||
|
||||
| akizelokro |
|
|||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
В какой такой процедурной парадигме? С одного момента начинается полный завал, когда количество функций превышает определенное число. Классы позволяют их группировать и достаточно удобно менять. И ты меня не понял. Я тебе говорил про какую модель? Про формально однострочные выражения. если у тебя "а + дробь", то а парсится как однострочное выражение, для плюса ты можешь оператор сделать со своеобразным поведением, или приписать как данные в класс (сам придумай как, это уже мелочи). Дробь же парсится дальше на класс выражения, в котором есть указатели на числитель и знаменатель (которые в свою очередь экземпляры класса однострочного выражения). И так там рекурсивно доходится до конца. И когда появляется четырехэтажная дробь (видел и такие), то там разбираться она будет на основе уже написанного кода, а не придётся всё переписывать и переделывать -------------------- a = a + b; b = a - b; a = a - b; |
|||
|
||||
| ТарасАтавин |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 370 Регистрация: 26.8.2013 Репутация: нет Всего: нет |
Добавлено @ 07:08 Как вообще можно классом что либо делать с функциями вне самого класса? Попутка же свалить в класс не относящиеся к нему функции вызовет завал уже на первой такой функции и разгрести его будет не возможно. К тому же по требованию задачи все фигурирующие в выражениях функции должны быть даже вне самого проекта. Это сообщение отредактировал(а) ТарасАтавин - 3.9.2013, 07:10 -------------------- Не так всё плохо, как оно есть на самом деле. |
|||
|
||||
| akizelokro |
|
|||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
Имеет огромное значение и количество функций. Потому что при изменении кода, если они не структурированы, то уже не помнишь что они делают. И теряешь время на переход и поиск места в коде. Элементарные же вещи. А когда надо обратиться через год даже к своему коду, то чтобы помнить, что и как, надо обладать феноменальной памятью. Но это есть только у уникумов. А люди, как правило, не таковы. -------------------- a = a + b; b = a - b; a = a - b; |
|||
|
||||
| ТарасАтавин |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 370 Регистрация: 26.8.2013 Репутация: нет Всего: нет |
Если ты даже парадигм не знаешь, то иди ка сначала в википедию, на форум тебе рановато.
-------------------- Не так всё плохо, как оно есть на самом деле. |
|||
|
||||
| akizelokro |
|
|||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
Я знаю, что такое парадигмы, не беспокойся. И знаю, что некоторые на классах умудряются реализовывать процедурную парадигму. Ещё вопросы есть? -------------------- a = a + b; b = a - b; a = a - b; |
|||
|
||||
| ТарасАтавин |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 370 Регистрация: 26.8.2013 Репутация: нет Всего: нет |
Не имеет. От функции у меня есть идентификатор типа std::wstring, я его вывожу, как обычную подстроку и всё. И даже таблица функций прямо здесь не нужна. А готовая разметка потом будет передана в другую программу, задача которой уже трансляция в исполняемый код. И кот там то и будет строиться дерево объектов, но без визуализации. Там количество функций тоже не имеет значения. И там уместна объектная парадигма, но задача другая - разобрать разметку с учётом приоритетов операций, арифметических и операторных скобок и тому подобной иерархии и сгенерить код.
Добавлено @ 07:26 Нет. Забыть назначение функции во-первых не возможно. Во-вторых любая функция легко читается. А в-третьих функции самого проекта не участвуют в выражениях, а участвующие не входят в проект. А вот если класс "притянуть за уши", то его назначение гарантировано забудется уже в процессе декларации его интерфейса. Это сообщение отредактировал(а) ТарасАтавин - 3.9.2013, 07:26 -------------------- Не так всё плохо, как оно есть на самом деле. |
|||
|
||||
| ТарасАтавин |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 370 Регистрация: 26.8.2013 Репутация: нет Всего: нет |
Я могу до символа повторить программу, написанную ещё в 1995-м году со всеми допущенными ещё тогда ошибками и избыточностями. А на одном проекте у меня была напарница, забывавшая точное имя функции в процессе её реализации. Но даже она не путалась их назначении, а только забывала, что и как именно сокращено, что написано полностью и как правильно такой то слог пишется по-английски. Назначение же она просто читала в комментариях к прототипам. Имя оба противоположные варианты феноменальной памяти, на выбор нужной функции при её использовании мы умудрялись тратить примерно одинаковое время. Ни добавление новых функций, ни замена существующих не мешала не только мне, но и ей. Но даже я со своей памятью не способен надолго запомнить назначение избыточного класса. Уже, кстати, пробовал. Назначение класса забывалось минуты через две, приходилось возвращаться к комментарию и только тогда продолжать. Тот класс я только декларировал трое суток, а как дошёл до реализации, догадался полностью заменить всю иерархию, тогда дело и пошло. Для того, чтоб при избыточности держать в памяти целый класс, она должна быть совсем уж как у машины. Я читал и вообще чужие проекты полностью в процедурной парадигме и потом брал из за основу своих проектов. Ни одна подпрограмма не вызвала затруднений. И даже на спектрумовском бейсике, поддерживающем только алгоритмическую парадигму в чистом виде. Единственная сложность данной задачи заключалась в том, что на выходе нужна высота только числителя, а высота вложенной дроби предварительно должна оцениваться целиком, а при выводе опять только высота числителя, но функций оценки высоты желательно иметь две перекрёстно рекурсивные для дроби и одноэтажной строки. Как только догадался вернуть оба значения в полях одного объекта, всё решение стало элементарным. Но объект здесь - не дробь, а высота. Можно было бы и два скалярных выходных параметра вместо него использовать. Сложность и результат те же. Это сообщение отредактировал(а) ТарасАтавин - 3.9.2013, 07:53 -------------------- Не так всё плохо, как оно есть на самом деле. |
|||
|
||||
| akizelokro |
|
|||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
Тгда ты практически феномен и тебе можно гордиться. Люди, даже если будут тренирвоать свою память, именно таких успехов, как правило, не добьются. Но и тебе надо учитывать, что они, как правило не таковы. В этом нет ничего плохого, просто жизнь разнообразна. Я вот что-то такое предполагал, кстати. -------------------- a = a + b; b = a - b; a = a - b; |
|||
|
||||
| ТарасАтавин |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 370 Регистрация: 26.8.2013 Репутация: нет Всего: нет |
Кстати, классы ни чего не добавляют к возможностям группировки функций, для этого более, чем достаточно использовать части имён. Классы нужны для группировки данных: A::method() или AMethod(A &a) разница не велика, а имена данных пришлось бы составлять из имён не классов и полей, а объектов и полей, а таких объектов может быть много и хуже всего становится, когда они ещё и элементы массивов. Сколько массивов придётся индексировать, чтоб достучаться к 10-ти свойствам одной сущности? А с помощью объектов можно индексировать один массив, сохранить, если надо, адрес элемента в указатель и потом юзать поля. А методы (подпрограммы-члены) нужны для доступа к приватным и защищённым членам и не только на плюсах. Разделение класса на интерфейс и сокрытые данные - не флаг константности, а реальная возможность упростить структуру объектно-ориентированного проекта и для всех функций сразу записать, что именно должно быть защищено, или запривачено: одно дело, разработка одной маленькой функции, и совсем другое доступ к данному через 10 лет для других целей в шестиуровневой иерархии классов. В первом случае доступ вытекает из текущей подзадачи и забыть его невозможно, а во втором доступ определяется назначением всей иерархии и влияет на сами подзадачи.
Добавлено @ 07:53
Это сообщение отредактировал(а) ТарасАтавин - 5.9.2013, 08:04 -------------------- Не так всё плохо, как оно есть на самом деле. |
|||
|
||||
| akizelokro |
|
|||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
Это всё понятно, что есть таковы варианты рассуждений. Но истина где-то посередине.
И заключается она в том, что перегрузка операторов в ООП это не способ упорядочить объекты, а способ упорядочить функции, работающие собъектами. Я думаю, что и процедурной парадигме, и в ООП-ориентированной есть свои примеры хорошей организации дела, и есть плохие. -------------------- a = a + b; b = a - b; a = a - b; |
|||
|
||||
| ТарасАтавин |
|
||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 370 Регистрация: 26.8.2013 Репутация: нет Всего: нет |
Перегрузка операторов - это способ создать функции с синтаксисом операторов. В данном же случае нужны функции с синтаксисом обычных подпрограмм. И всякая группировка функций членством в классе основана только на данных и призвана распределить доступ. Даже перегруженные операторы могут быть вне классов, ни кто не запрещает перегрузить
Это сообщение отредактировал(а) ТарасАтавин - 7.9.2013, 06:22 -------------------- Не так всё плохо, как оно есть на самом деле. |
||||||
|
|||||||
| akizelokro |
|
|||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
Этот материал мне знаком ,спасибо за лекцию.
А реальность такова. Что создавая тип данных, обязательно нужен функционал к нему. Ну, необязательно, но данные тогда мало что значат. Так что кроме упорядочения данных приходится зубрить и большую портянку функций к нему. И это ещё зашибись, если для похожих типов данных не придумывают новых названий функций. -------------------- a = a + b; b = a - b; a = a - b; |
|||
|
||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |