Я прочитал, но мне не удалось ответить на свой вопрос.
Прочитали или пробежались? Пример реализации Transform
ведь делает то что вы спрашиваете - вызов переданной функции внутри другой подпрограммы.
Как в заголовке подпрограммы указать, что тип может быть любым? procedure Backspace(f: <T>-><T>; var a: <T>; params i: array of <T>)
не работает.
Полный код (на всякий случай):
procedure Backspace(f: <T>-><T>; var a: <T>; params i: array of <T>);
begin
var x := Console.CursorLeft;
var y := Console.CursorTop; // сохранение положения курсора
a := f(i); // значение функции
var m: integer;
if (Console.BufferHeight > Console.WindowHeight) then m := Console.LargestWindowWidth - 3 else m := Console.LargestWindowWidth; // расчёт количества символов, которое влезет в окно текущей ширины
var l := a.ToString.Length; // длина введённых данных
x += l;
while (x >= m) do
begin
x -= m;
y += 1; // расчёт положения курсора сразу после ввода
end;
Console.CursorLeft := x;
Console.CursorTop := y; // восстановления положения курсора
end;
Ну как минимум потому что учите более базовый синтаксис перед тем как приступать чему то более сложному. Шаблоны записываются так:
procedure p1<T>(a: T);
<>
стоит только после имени подпрограммы и перечисляет все имена которые считать шаблонным типом. А в описании параметров надо писать просто T
.
<>
в типах параметров может быть только если вы используете шаблонный класс/запись в параметрах:
type
t1<TVal> = class
val: TVal;
end;
procedure p1<TArg>(a: t1<TArg>);
А вообще какие шаблоны, тут надо f: ()->string
. Возвращать надо именно string
, потому что, к примеру, при вводе числа - можно поставить пробелы слева и справа от числа при вводе. Тогда получится что ввели больше символов, чем надо чтоб представить это число после .ToString
.
И аргументы f
тут ни к чему, вы же пишете не инвоук для вызова между доменами.
Это всё для поддержки функций, у которых вывод осуществляется и в параметры, и в Result
, например, function TryRead(var x: число): boolean
.
Тогда следует считывать в строку, брать её в длину и преобразовывать строку в тип, соответствующий параетру-функции?
TryRead
тут не сработает, раз число нельзя вводить напрямую. Но если нужна проверка ввода - то её надо делать ручками:
procedure Backspace(f: ()->string);
begin
//ToDo
end;
begin
Backspace(()->
begin
while true do
begin
Result := ReadString;
if Result.All(ch->ch.IsDigit or char.IsWhiteSpace(ch)) then
break;
Writeln('Повторите ввод');
end;
end);
end.
Как направить в ReadLexem
строку вместо ввода?
ReadLexem
имеет алгоритм, оптимизированный на потоки данных (System.IO.Stream
) и привязанный к потоку ввода. Можно перенаправить весь поток ввода на строку в памяти (в том числе временно).
Но это скорее костыли, потому что если вам надо вытащить слово из строки - надо использовать методы работы со строками, а не пытаться прикрутить методы работы с потоками. Тогда код будет и эффективнее, и проще:
##
var ind := 1;
var s := ReadString;
while ind<>s.Length do
s.ReadWord(ind).Println;
Почему не работает?
uses GraphWPF;
begin
var x:=ReadInteger;
или var x:=ReadReal;
end.
Как мне теперь считать значение с клавиатуры?
System.FormatException: Входная строка имела неверный формат.
Всё работает. Вводить надо в ту же строку ввода, что и в консольной программе. Если не делать ошибок при вводе, такого исключения быть не должно.
Проблема появляется, только если подключить GraphWPF
. У меня всё работает только в окне IDE. Как только ввод направляется прямо из окна консольного приложения, так сразу вылетает исключение. (Кстати, исключение можно не заметить, если не вызвать запись в окно консоли, поскольку запрос на ввод числа и последующее исключение не вызывают выделения консольного окна.)
В случае с ReadString
окно не реагирует на нажатия клавиш при вводе, кроме как при нажатии клавиш пропадает выделение.
Такое чувство, что ввод отрезан от окна консоли.
Графические приложения не предназначены для работы с окном консоли
Ясно. Тогда как считывать что-либо с клавиатуры (особенно не отдельные символы, а подлиннее, но и отдельные будут полезны)?
Графический экран при подключение через uses будеть работать всегда, не даёт помехи для ввода с клавиатуры
Так у меня не работает ReadInteger
при выполнении без связи с оболочкой (Shift+F9):
Программы с модулем GraphWPF не предназначены для компиляции и выполнения без связи с оболочкой, если в них используются подпрограммы ввода?
Если нет консоли, а Вы указываете консольный ввод, что по-Вашему программа должна делать?
Это работает только в IDE.
и иметь возможность запустить эту скомпилированную программу с подключённым модулем GraphWPF?
Никак. GraphWPF для этого не создавался