Форум «Всё о Паскале» _ Задачи _ Как передать в функцию переменную любого типа?
Автор: kramolnic 16.03.2007 2:20
Возникла необходимость написать процедурку, которая будет выводить текст с форматированием относительно окна (по центру, справа, слева и т.п...)... Стандартная процедура ReadLn или WriteLn да и куча им подобных может принимать в качестве параметра переменную любого типа и работать с ней.. можно распечатать и String и Integer... а как объявить свою процедуру, чтобы она могла делать так же?? то есть как не привязывать параметр к определенному типу?? P.S. параметр должен передаваться по ссылке (со словом var).
Автор: volvo 16.03.2007 2:30
Цитата
Стандартная процедура ReadLn или WriteLn
Ошибка... ReadLn/WriteLn - это макросы, ничего общего с процедурами не имеющие... А чтобы передать любой параметр, передавай его вообще без типа:
Procedure p(Var X); begin end;
(только тогда ты должен будешь привести внутри процедуры переменную X к нужному типу)...
Вообще, разговор получается беспредметный. Приведи пример, ЧТО именно ты хочешь делать в процедуре, и КАК вызывать ее, посмотрим, что для этого можно сделать... Общий случай здесь не пойдет...
Автор: kramolnic 16.03.2007 2:38
Цитата(volvo @ 15.03.2007 22:30)
Ошибка... ReadLn/WriteLn - это макросы, ничего общего с процедурами не имеющие... А чтобы передать любой параметр, передавай его вообще без типа:
О как! а я то думал, что процедура, объявленная где нить в дебрях паскаля... ну скажем, хочу я вывести число по центру, а ниже строку, юзая свою процедуру или что там... Вызываем это дело, например, так...:
Код
var k: integer; s: string; begin k:= 2345; s:= 'This is my text'; WriteCenter(k); writeln(''); WriteCenter(s); end;
вот как эту WriteCenter описать, чтобы она обе переменные нормально приняла (тип-то разный), вычислила координаты X, Y, куда выводить строку (видимо, все равно придется к Stringу привести, чтобы число символов посчитать), сделала GoToXY и потом Write(param), где param - параметр, передаваемый процедуре...
Автор: volvo 16.03.2007 3:27
Извращение конечно еще то, но все-таки... (если уверен, что хочешь это видеть - нажми мышкой на спойлер, не открываю сразу, может у кого-то будут еще варианты)
Спойлер(Показать/Скрыть)
type pr = ^r; r = record case _type: integer of 1: (var_int: integer); 2: (var_float: real); 3: (var_str: string); end;
function _integer(X: integer): pr; var _result: pr; begin _result := new(pr); _result^._type := 1; _result^.var_int := X; _integer := _result; end;
function _float(var X: real): pr; var _result: pr; begin _result := new(pr); _result^._type := 2; _result^.var_float := X; _float := _result; end;
function _string(var X: string): pr; var _result: pr; begin _result := new(pr); _result^._type := 3; _result^.var_str := X; _string := _result; end;
procedure WriteCenter(X: pr); begin case X^._type of 1: writeln(X^.var_int:10); 2: writeln(X^.var_float:10:5); 3: writeln(X^.var_str:20); end; dispose(X); end;
var k: integer; s: string; begin writeln('before: ', memavail); { <--- Вот это ... }
k:= 2345; s:= 'This is my text'; WriteCenter(_integer(k)); writeln(''); WriteCenter(_string(s));
writeln('after: ', memavail); { <--- ... и это - для проверки, что нет утечек памяти } end.
Автор: мисс_граффити 16.03.2007 4:17
Цитата
Возникла необходимость написать процедурку
Возникла для сугубо практических целей? Или должно быть написано именно на паскале?
Автор: kramolnic 16.03.2007 4:41
Цитата(мисс_граффити @ 16.03.2007 0:17)
Возникла для сугубо практических целей? Или должно быть написано именно на паскале?
Именно для практических целей... и именно на Паскале. Но на самом деле было больше интересно, как это в паскале реализуется такая вещь. Я-то думал, что read и write процедурами являются. Думаю, проще просто текстовое значение в качестве параметра принимать и его выводить. Придется только преобразовывать типы в String... эх... прям как в старые добрые времена в Delphi там достали эти преобразования, так теперь еще и здесь...
Автор: мисс_граффити 16.03.2007 4:56
Ясно. Я просто хотела предложить посмотреть в сторону java... Там это несложно реализовать. *задумалась, считать ли это свое сообщение нарушением правил.
Автор: volvo 16.03.2007 5:16
Цитата
на самом деле было больше интересно, как это в паскале реализуется такая вещь.
На самом то деле в Паскале такое реализуется ГОРАЗДО проще, чем ты можешь себе предстаить, только вот почему-то у многих выработался рефлекс: как только видят в программе слово Object - дальше программа не читается... А зря... Смотри:
type pT = ^T; T = object constructor create; procedure Print; virtual; end;
constructor T.create; begin end; procedure T.print; begin end;
constructor Tstring.create(s: string); begin inherited Create; data := s; end; procedure Tstring.Print; begin writeln('<' + data + '>') end;
constructor Tinteger.create(i: integer); begin inherited Create; data := i; end; procedure Tinteger.Print; begin writeln(data:10); end;
procedure WriteCenter(Obj: pT); begin Obj^.Print; end;
begin WriteCenter(new(pTinteger, create(2345))); writeln(''); WriteCenter(new(pTstring, create('This is my text'))); end.
Что, ЭТО не Паскаль? Почему же вы выбрасываете из языка ее самую мощную часть?
Автор: Bokul 16.03.2007 5:22
Вопрос: для чего при наследовании ты используешь inherited, вместо простого перекрытия?
Автор: volvo 16.03.2007 5:35
Привычка... Я всегда инициализирую всю цепочку (третий инициализируется вторым, который в свою очередь инициализируется первым)... Возможно, мне понадобится добавить еще один тип МЕЖДУ уже описанными (скажем, перед Tstring), тогда Inherited спасает меня от лазания по коду, как если бы я написал:
constructor Tstring.create(s: string); begin T.Create; data := s; end;
а представляешь, если у тебя иерархия из десятка уровней, и нескольких десятков классов? Где-то надо менять, где-то не надо... Веселуха...