Помощь - Поиск - Пользователи - Календарь
Полная версия: Для Тех Кто Реально разбирается в "turbo Pascal"
Форум «Всё о Паскале» > Pascal, Object Pascal > Теоретические вопросы
Reople
Доброго времени суток, знаток Turbo Pascal'я (если нет, то можешь дальше не читать).

У меня Есть 2 Вопроса по Turbo Pascal 7.0:

1) Это даже не вопрос, а факты о противоречии разных авторов об одних вещах, - вопрос касается <структуры> Множество <set of ...>
Привожу Цитаты:
a) <... Исходя из особенностей внутреннего представления множеств можно сделать два основных вывода: [...] - все операции над множествами выполняются значительно эффективней, чем над другими структурами данных>
Рапаков Г. Г. (или как там), Ржеуцкая С. У. "Программирование на языке Pascal" Spb 2004. стр 282
б)<... Одна из причин редкого применения - очень низкая скорость выполнения операции с множествами.>
Издательская группа BHV "Турбо Паскаль 7.0" Киев 1999г. стр 157

Исходя из внутреннего устройство множества в Tubo Pascal я склонен верит первому высказыванию, и смело переписал некоторые фрагменты одной своей программы с их помощью. However, работа с отдельными битами нам не разрешена (даже в asm'е мы логически складываем, умножаем отдельные БАЙТЫ, чтобы переключить нужный нам бит). У кого-нибудь есть размышления (а лучше конкретные факты в пользу одной из двух высказываний).

p.S. Если кто-то посоветует сравнить книги по остальному содержанию, то он может дальше не читать

2) Вопрос второй касается распределения памяти. Вот фрагмент программы, которая корректно работает:
Главный Pas файл.
{=============================================} 
{ Программа просит ввести аргументы и соответствующие им значения
функции. Затем Она Интерполирует их методом Лагранжа и получает
уравнение для зависимости. Далее Программа строит график этой функции
}
{ например вы знаете что x0 = 0 y0 = 0; x1 = 2 y1 = 4; x3 = 1; y3 = 1;

а она вам скажет что f(x) = x^2 }
{$N+}
Uses Crt, Polynom, Graph;
Const
lY: longint = 0; { Количество аргументов }
Var
i, j : integer; { счетчики }
pMassY: PdMass; { значения функции }
pMassX: PdMass; { аргументы }
pPolin: PdMass; { Указатель на полином }
pFunk : pointer; { Указатель на функцию }

procedure Init;
begin
{ Ввод pMassX и pMassY }
end;

{ Дальше я построю график данной функции }
function f(x: double): Double; far;
{ Считаем полином }
Var
i: integer;
y: Double;
begin
y:= pPolin^[1];
for i:= 2 to lY do y:= y * x + pPolin^[i];
f:= y
end;
{----------------------------------------------------------------------------}
begin
Init;
pPolin:= pBuildPol(lY, pMassX, pMassY); { Вот наш полином!!!!!!!!!!!!!!!! }
{ Включаем графику }
{ Сохраняем адрес функции, чтобы передать его в процедуру }
pFunk:= @f;
{ Передаем указатель на аргументы, их количество, указатель на функцию, и координаты окна в котором вывести график }
DrawShedule(pMassX, lY, pFunk, 30, 30, 600, 400);
{ Выключи графику }
...
end.


{---------------------------------------------------------------------------------} 
{ А вот модуль Polynom, где процедура DrawShedule }{=============================================}
{$N+}
Unit Polynom;
interface
....
Type
...
TFunk = function (x: double): Double;
...
procedure DrawShedule(... p: Pointer...);
{ тут p = @f }
....
implementation
...
procedure DrawShedule(... p: Pointer ...); { тут p = @f }
....
Var
f : TFunk; { функция, график которой надо построить }
begin
....
@f:= p; { связываю переменную f с функцией адрес, которой лежал в p}
...
{ И используем её }
dX:= f(x)
end;
...
end.
{==============================================}

Вот таким способом я передал функцию в процедуры построения графика. Немного короче было бы передать функцию так
procedure DrawShedule(... f: TFunk ...); а вызов DrawShedule(... f ...);
Но об этом разговор дальше.

Так программа рабочая, я вставляю текст в виртуальный метод в другой программе
{==============================================} 
interfaсe
.............
TMass = Object(TAssembly) {TAssembly - абстрактный класс }
Private
{ Данные } ...
Public
{ Методы } ...
Procedure Job; Virtual; {вот сюда}
end;
............
implementation
............
Procedure TMass.Job;
Var
......
pPolin: PdMass; { Указатель на коэффициенты полинома }
pFunc : Pointer;
......
{----------------------------------------------------------------------------------}
function f(x: double): Double; far;
{ И Горнор пригодился/ или Горнер xD }
Var
i: integer;
y: Double
begin
y:= pPolin^[1];
for i:= 2 to lX do y:= y * x + pPolin^[i];
f:= y
end;
{-----------------------------------------------------------------------------------}
begin
pFunc:= @f; { Сохраняем адрес }
pPolin:= pBuildPol(lX, pMassX, pMassY); { Вот наш полином!!!!!!!!!!!!!!!! }
{ Включаем графику }
{ Покажи график }
DrawShedule(... pFunc ...);
{ В гробу я видел эту интерполяцию xD }
end;
......
end.
{ Модуль Polynom остался прежним }
{==============================================}

Так Вот, Господа, приверженцы передачи имени процедуры с помощью типа в данном случае компилятор даже не захочет с вами общаться, Утверждая, Что то, что вы передаете в процедуру DrawShedule(... f ...) не указывает на область памяти, это про "f".

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

Они связанны с.....?? Это и есть мой вопрос.

Мой рассуждения. У виртуального метода локальная функция хранится либо в стеке, либо в сегменте кода, поэтому компилятор не захочет передавать имя функции в качестве формального параметра, ведь он боится, что на этапе позднего связывания, он не сможет определить расположение функции.

Рассуждения, как решить проблему: расположить код функции по конкретному адресу в памяти ( где-то тут $C000:0000 ) - Но как это реализовать?

А еще может мои рассуждения просто чушь, Посему я и обратился к Вам! Тема покажет, какие тут программисты на форуме.


p.s.s отдельная программа работает, как и при передаче имени функции, так и при передачи её адреса (как я написал). В виртуальном методе при передачи имени функции компилятор не захочет с вами иметь дело. А вот при передачи адреса он с вами будет дружить, он то будет, а вот процессор нет...

Ну, ваши соображения, уважаемые пользователи форума!
Не Забывайте я задал 2 вопроса
volvo
Цитата
<... Исходя из особенностей внутреннего представления множеств можно сделать два основных вывода: [...] - все операции над множествами выполняются значительно эффективней, чем над другими структурами данных>

Полностью согласен... Неоднократно убеждался в этом на практике... Недостатки множеств - ограниченная емкость и невозможность обращаться напрямую к элементам множества... Что касается быстродействия - множества быстрее. :yes: Если найду программку - выложу...


Цитата
Тема покажет, какие тут программисты на форуме.

Не зарывайтесь !!! angry.gif Приведите не эти обрывки, а нормально компилирующуюся программу, если хотите, чтоб Вам помогли в чем-то разобраться.

Кстати, на форуме для кода есть теги, наличие которых Вы проигнорировали... Почему?
-reople-
Во-первых, выражаю вам благодарность Volvo за сообщение. Я проигнорировал теги, потому что посчитал, что мои тексты и культ розового в разных ипостасях.

Насчет не зарываться....хм.... только ТЫ, ответил.... и ТОЛЬКО НА ОДИН ВОПРОС!!!!!!!

Увы, но приводя нормально компилирующие тексты, я отвлеку внимания читателя массой ненужных текстов, а тут я писал только то, что нужно. Тема ведь ТЕОРИТИЧЕСКИЕ ВОПРОСЫ??? причем тут то, что можно скомпилировать.

Ещё, я нашел ответ на свой второй вопрос - очень интересный недостаток TURBO PASCAL выискался, однако!

Volvo, задай себе вопрос : "ПОЧЕМУ на форуме, посвященному Turbo Pascal только я смог ответь и только на один из 2 вопросов".

Люди давайте развиваться!
И выкладывайте своё мнение!!!!!
-reople-
thx Oleg_Z. И вправду красиво получилось..... и что самое ГЛАВНОЕ, БЕз РОЗОВОГО!

p.s. ещё раз thx. - в частности зато, что ты мне показал, КАК нужно выкладывать исходники.
Romtek
Я так и не понял в чём проблема. Не получается вызвать процедуру из модуля, вставив адрес передаваемой процедуры f ?

Приводи рабочие исходники, а не свои доводы.

Вот писал когда-то программу с использованием процедурных типов:
type
XType=word;
TProcedure=Procedure (x: XType);

Procedure ForStep(_from,_to,step: XType; P: pointer);
var z: XType;
F: TProcedure;
begin
@F:=P;
z:=_from;
while z<_to+Step do
begin
F(z);
inc(z,Step);
end;
end;

Procedure Cycle(x: XType); far;
begin
writeln(x)
end;

begin
ForStep(1,15,2,@Cycle);
end.
volvo
Цитата(-reople- @ 29.05.05 20:00)
Volvo, задай себе вопрос : "ПОЧЕМУ на форуме, посвященному Turbo Pascal только я смог ответь и только на один из 2 вопросов".

Ну, в таком случае - вот ответ на второй вопрос:

Вся проблема в том, что функция F() описывается локально (вложенной в один из методов объекта). Именно пожтому и невозможно передать имя процедуры, а возможно - только ее адрес.

Но неужели ничего нельзя сделать для того, чтобы программа заработала? Да можно конечно. Любой, кто сталкивался с объектами TurboVision сразу найдет связь между описанием функции F() и описанием тех функций, которые передаются как параметры, ну например в TGroup.ForEach(Action: Pointer), не так ли? Та же самая локальная процедура (функция), с директивой Far...

Как заставить F() работать? Точно так же, как ForEach() заставляет работать Action:
procedure TGroup.ForEach(Action: Pointer); assembler;
var ALast: Pointer;
asm
mov ecx,Self
mov ecx,[ecx].TGroup.Last
jecxz @@RET
mov ebx,Action
mov ALast,ecx
mov ecx,[ecx].TView.Next
@@1:
cmp ecx,ALast
je @@2
push [ecx].TView.Next
push ecx
Call ebx
pop ecx
jmp @@1
@@2:
push ecx
Call ebx
@@RET:
end;
AlienEmperor
2 Reople: вот сейчас все брошу и буду над Вашими проблемами сидеть... smile.gif
Сам с такой проблемой не сталкивался (все-таки Turbo Pas сегодня - это скорее развлечение, а не работа), а сидеть и решать проблемы, которые самому на фиг не нужны - несколько не интересно... Говорит ли обо мне это как о плохом программисте ? Мое руководство так не считает.

2 Volvo: А разве на Turbo Pascal такая тема: Mov ECX,Smth прокатит ? Этож 32 разрядная операция ? Или я что-то не так понял ???
-Reople-
Volvo ты самый ЛУЧШИЙ! БОЛЬШОЕ спасибо за реальный ответ, но увы, мне он не подходит...
1) О библиотеке TurboVision читаю (ни разу не от кого не слышал! - хотя эта норма для всех кто программирует) второй раз.

2) Из- за чего мне не понятны следующие операнды <TGroup.Last> <TView.Next>
( кажется методы объектов)

3) Я пишу 16р программу в которой по идее не используются расширенные регистры ECX и EBX (или я дятел, который чего-то не знает и долбит?)

4) TGroup.ForEach(Action: Pointer); assembler; - МЕТОД.
Я же вызываю ПРОЦЕДУРУ из другого модуля в которую и передаю адрес локальной функции метода из которого и происходит вызов. Из твоего ответа я понял, что мне надо переписать ПРОЦЕДУРУ на асме? НО её я не перепишу на асме даже за 4 дня! (потому что я знаю недостаточно и мне придется копаться в книгах, а этого времени у меня нет). и к тому же пункт 3
Да, локальные подпрограммы могут иметь только ближний тип вызова - И ОНИ не могут внешними или иметь дальний тип вызова. - это ты прав, и это надо как-то исправить.


Volvo, а ты можешь доступным (для дятлов типа меня) языком об'яснить, по какому принципу это заработает. Как метод узнает адрес функции, которую нужно вызвать и из-за чего с этим адресом надо что-то делать и, вообще, где хранится локальная функция виртуального метода.

И возможно ли локальную функцию вирт.метода сделать внешней (external) { просто я переписал эту функцию на асме и сравнив код могу заявить, что она будет работать быстрее}

Надеюсь на твой ответ, как на жизнь после смерти.

Romtek, thx за ответ, но ответы типа делай как я, мне не помогут.
Может у тебя ещё что-нибудь есть?
Guest
На чем писать руководство скажет на том и будешь, сказано TP - твоя задача сделать. Почему я не знаю библиотек Turbo Pascal? - потому что там, где не указывают я пишу на С++
-reople-
последнее сообщение моё. про <руководство и С++>
Romtek
Вот состряпал пример, надеюсь поможет (с указателем и без):
program Using_procedural_types;

type
Proctype = function (x: real): real;

function MyFunc (x: real): real; far;
begin
MyFunc := x * x
end;

function MyFunc2 (x: real): real; far;
begin
MyFunc2 := x * x
end;

procedure X (P: pointer);
var F: Proctype;
begin
@F := P;
writeln (F (15.1) : 10 : 2)
end;

var F: Proctype;
begin
writeln;

F := Myfunc;
writeln (F (23.7) : 10 : 2);

x (@Myfunc);
end.
-reople-
Romtek, thx - но это не поможет, это мы и сами умеем. - тут проблема в другом, в том, что функция "пропадает" по адресу в котором находилась. Она находится в сегменте кода вместе с методом, я передаю её адрес в другой модуль и в нем присваиваю локальной переменной (типа функция) её адрес, но когда идет вызов "новой" функции может произойти всё, что угодно.
Romtek
Приведи всё же пример, гость -reople-.

На примере и поможем.
volvo
Цитата(-reople- @ 30.05.05 21:02)
Она находится в сегменте кода вместе с методом, я передаю её адрес в другой модуль и в нем присваиваю локальной переменной (типа функция) её адрес

:no: Не думай об этом... Для тебя то, что функция находится в сегменте кода СОВСЕМ не важно. В тот момент, когда ты передаешь адрес этой функции в свою процедуру виртуальный метод активен, следовательно он (ну и естественно все его локальные функции) загружается в стек... Вот об этом тебе нужно подумать...

А вообще Romtek прав, прикрепил бы ты архив с программкой...
Reople
Ладно. ВОт шаблон (уреза вроде все, а проблему оставил). Практикуйтесь и рассказывайте о результатах!

p.s. Файлы
Глобальный допустимый размер: размер неограничен

p.s.s Вы использовали 2.37кб места для присоединений к этому сообщению.Вам осталось 20мб для этого сообщения.

xex)
-reople-
Значит мне удалось выяснит следующие:

1) Функция вызывается та, что надо

2) Параметры передаваемые функции теряются, не воспринимаются, как будто их просто нет. Может не происходит "pop x"(так нельзя писать, но смысл понятный) и его надо вручную сделать, через асму.

3) из 2) возможно не восстанавливается стек нашей вызываемой функцией и из-за этого дальнейшие проблемы.

p.s. Только 4 человека решила попробывать свои силы?
-reople-
Народ просил исходники - я дал их.
Кажется, после этого народ умер...

:molitva: ГДЕ ВЫ?
hiv
Вот и все! Замени свой код:
Procedure TMass.Job;
Const rBuf: real = 15;
Var xa: byte;
{ xa. просто так. чтобы слово Var осталось.(а то совсем внешний вид изменился)}
function f(x: double): Double; far;
{ вот её и надо передать }
Var
i: integer;
y: Double;
begin
f:= rBuf * x { в этой функции я использую локальные описания TMASS.JOB }
end;
begin
WriteLn('Мы в виртуальном методе');
Write('Текущий сегмент кода : $');
Write(CSeg);
WriteLn;
Write('Переменная f по смещению : $');
Write(Ofs(f));
Write(' в сегменте : $');
Write(Seg(f));
readln;
DrawShedule(pMassX, lX, @f, 30, 30, 580, 400);
ReadKey
end;

на этот:
Const rBuf: real = 15;
function f(x: double): Double; far;
{ вот её и надо передать }
Var
i: integer;
y: Double;
begin
f:= rBuf * x { в этой функции я использую локальные описания TMASS.JOB }
end;

Procedure TMass.Job;
Var xa: byte;
{ xa. просто так. чтобы слово Var осталось.(а то совсем внешний вид изменился)}
begin
WriteLn('Мы в виртуальном методе');
Write('Текущий сегмент кода : $');
Write(CSeg);
WriteLn;
Write('Переменная f по смещению : $');
Write(Ofs(f));
Write(' в сегменте : $');
Write(Seg(f));
readln;
DrawShedule(pMassX, lX, @f, 30, 30, 580, 400);
ReadKey
end;

Т.Е. определение твоей ф-ции F(x) ограничивалось пространством процедуры TMass.Job, а ты пытался ее вызвать вообще из другого места программы, вот стек и сбоил. Я ее вынес - и все заработало!
-reople-
smile.gif Молодец Hiv, долго думал? - наверно нет.

Пока у тебя самый реальный ответ на мой вопрос, почему пока? теме разве не закрыта? Попытаюсь прояснить...

Цитата("me")
f:= rBuf * x {  в этой функции я использую локальные описания TMASS.JOB }


В методе TMASS.Job формируется указатель на ещё один массив pPolin^. Переносить локальные описания в секцию implementation - лучше застрелите меня. - Зачем тогда вообще ООП? Можно было перенести функцию f в модуль Polynom, и передавать в DrawShedule(pMassX, lX, pPolin, 30, 30, 580, 400); локальные данные, которые использует функция f - можно, но не положено. Потому, что процедура будет строить график только для полиномов, а может для всего (процедуру я писал универсальную). Возможны ошибки, так как к данным типа rBuff получают доступ все методы модуля, выше которых они описаны. (Придется писать все время в конце... это хорошо?)

Цитата
Т.Е. определение твоей ф-ции F(x) ограничивалось пространством процедуры TMass.Job


Идея хорошая, но виртуальный метод активен и не завершил свою работу, когда вызывается функция f из модуля Polynom.

Перед вызовом процедуры f из модуля Polynom я написал следующие:

asm { y я описал в процедуре DrawShedule// Const y: double = 15}
mov ax, WORD PTR Y
mov bx, WORD PTR Y + 2
mov cx, WORD PTR Y + 6
mov dx, WORD PTR Y + 8

push ax
push bx
push cx
push dx
end;

И вы представляете, параметр действительно передается в функцию, тока...
тока с погрешностью на каждую 10 - 0.125.



НУ есть идей, как развить мысль? или как сделать по человечески?

p.s. Интересно, сколько людей используют описания в секции implementation?
hiv
Если по человечески - то если начал писать в ООП, то и пиши все в ООП. Т.е. твоя ф-ция наверняка будет тобой или еще кем-то меняться на свою, вот и определи ее как один из методов твоего объекта и сделай ее виртуальной, чтобы потом ее можно было перегружать. А то что ты ее хоть и прописал внутри своего виртуального метода, то вызвать ее можешь только находясь внутри него, а хочешь использовать ее еще где-то. Ты сам себе противоречишь!
Цитата
Возможны ошибки, так как к данным типа rBuff получают доступ все методы модуля, выше которых они описаны.
Так опиши rBuff как поле твоего объекта и тогда все методы будут иметь к нему доступ.
-reople-
сделал методом - не помогает.

Может у тебя получится?
-reople-
Ну что, народ, сдались? Volvo и ты тоже? huh.gif
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.