Помощь новичкам

Если у Вас подразумевается серьезная работа с переборами в стиле брутфорса, тогда нужно действительно озаботиться оптимизацией, забыть о функциональном программировании и делать все на циклах. А еще лучше - реализовать это на С++, поскольку PascalABC.NЕТ никогда не позиционировался, как язык, дающий высокую степень оптимизации программ по времени исполнения.

Ну вот, хотел вспомнить как подвести две схожие функции под общую основу и снова получил замечания про анти-паттерны и совет писать на другом языке) Дело в том, что многое уже давно было реализовано на TP5+, но либо потерялось и устарело, либо опиралось на asm/inline, поэтому PABC.NEТ как раз подходит как по многообразию сути и формы написания, так и по требованиям памяти/скорости

1 лайк

Нельзя тут дать какой-то рецепт, если нет текста функций. В Fortran было хулиганство - определение точек входа в программные единицы. Т.е. пишутся отдельные Entry, а еще есть общая часть, реализующая общий же алгоритм. Но это идеология 70-х годов, почти полвека прошло, сейчас все иначе решается. Может, Вам проще сделать класс и там прописать какие-то методы. Надо смотреть тексты. И задачу саму. А то, быть может, на деле это художество и не нужно, а практичнее так и оставить две функции. Просто будут две функции с одним именем и разным набором параметров. И будет выбираться нужная автоматом.

  1. Попробовал пример не из PABC.NEТ для динамического парсинга Linq переписать на PABC.NEТ, но сразу застрял на неймспейсе:

uses System.Linq; 
{$reference System.Linq.Dynamic} // <-- АшЫпка!
begin
   var expression: string := '14 + 3 / 7';
   var func := System.Linq.Dynamic.DynamicExpression.ParseLambda(new ParameterExpression[0], typeof(double), expression).Compile();
   print(func);
end.

А сборки 3.5 и выше вроде должны держать, куда копать?

  1. Есть ли эквивалент или альтернатива старым директивам компилятора $I filename / $R filename, чтобы итого всё было в едином файле? Может какой-то Any2bin?

  2. Также в связи с подгрузкой значительного кол-ва внешних ресурсов (графика, звуки), чтобы не переизобретать, интересует рекомендуемый способ управления такими ресурсами (например, архив)

Спс

А .dll кто съел?
$reference прописывается не для неймспейсов а для библиотек, то есть .dll файлов. При этом в библиотеке может быть любое кол-во неймспейсов.

Можно использовать неймспейсы. Правда, придётся отлавливать много багов, и анализатор кода для них всё ещё не сделали.

Так же никто не запрещал вам найти чью то библиотеку в интернете.

1 лайк

На PABC нашёл пример OGL, но нет примеров [managed] DirectX. Подскажите, где глянуть и нужно ли какую-то SDK/библиотечку качать

Я пробовал SharpDX. Не сильно далеко продвинулся, хотя скоро понадобится. В общем найдёте хороший туториал по нему или что то типа того - напишите пожалуйста.

Задача: есть свёрнутое приложение-таймер, которое ожидает нажатие клавиши “Win” вместе с последующими цифрами. Например, удержание “Win” и нажатие “1” и “5” устанавливает таймер программы на 15 минут, не активируя форму. Так как .Net прямо не поддерживает глобальные хуки, думал через RegisterHotKey или API подыскать, но слишком много горячих клавиш получается…

Я всегда использую GetKeyState и не парюсь. У меня даже уже есть таймер (потому что без него у меня на плите всегда всё сгорает).

Правда, ввод устроен по другому, чтоб поставить на 15 мин - надо ввести 0:15. А чтоб ещё на 30 сек - 0:15:30. После этого консоль пропадает, но в любой момент можно нажать Ctrl+A и она появится снова (чтоб проверить сколько осталось).

Работает это всё криво (особенно FreeConsole глючно визуально работает, но хоть не ломает ничего), потому что я его заменить собираюсь (когда BH будет работать). Но вам оттуда нужна строчка:

  while ks.All(kk->GetKeyState(kk) shr 7 = $01) do

Это ожидание нажатия всех клавишь, номера которых хранятся в ks. Ещё, наверное, поможет WK.pas, чтоб узнавать номера каждой клавиши.

Ну и напоследок - ИМХО, но делать всё в бекграунд режиме, без каких то обозначений, или хотя бы писка System.Console.Beep после успешного ввода - это прямо просьба получить неприятности на 5 точку. Всегда что то может пойти не так. Вот я для этого сделал более простой ввод и возможность проверить, идёт ли таймер нормально.

1 лайк

Надо попробовать, чтобы не из пушки по воробьям)

Без активации формы не значит без feedback вообще: beep на каждом подтверждённом вводе и оглашение итога Text-To-Speech.

Почему так не работает, обобщенный тип для записи

type
  PNode = ^TNode<T>;
  TNode<T> = record
    data: T;
    next: PNode;
  end;
  
begin
  var p: PNode;
  New(p);
  p^.data := 'Hello';
  Writeln(p^.data)
end.

А шаблонный параметр T в выражении TNode<T> откуда брать должно?

type
  PNode<T> = ^TNode<T>;
  TNode<T> = record
    data: T;
    next: PNode<T>;
  end;
  
begin
  var p: PNode<byte>;
  New(p);
  p^.data := 'Hello';
  Writeln(p^.data)
end.

Так, конечно, другая проблема, потому что New не работает…

Получается нельзя?

Ну, криво но можно:

type
  PNode<T> = ^TNode<T>;
  TNode<T> = record
    data: T;
    next: PNode<T>;
  end;

procedure OtherNew<T>(var ptr: ^T);
begin
  var a: T;
  ptr := System.Runtime.InteropServices.Marshal.AllocHGlobal(
    System.Runtime.InteropServices.Marshal.SizeOf(a)
  ).ToPointer;
end;

begin
  var p: PNode<byte>;
  OtherNew(p);
  p^.data := 5;
  Writeln(p^.data)
end.

Marshal.AllocHGlobal использует и стандартное New():

      Program.@new((void*&) @numPtr, Marshal.SizeOf(typeof (byte)));
    public static unsafe void @new(ref void* ptr, int size)
    {
      ptr = (void*) Marshal.AllocHGlobal(size);
      Marshal.Copy(new byte[size], 0, (IntPtr) ptr, size);
    }

( New() это синтаксический сахар, поэтому то что кол-во параметров не совпадает это норма)

Но, Marshal.SizeOf не работает для шаблонных типов. Надо чтоб была переменная (как у меня - переменная a в OtherNew), чтоб вычислить размер. То есть для этого надо выделить лишнюю память. Хотя, в данном случае это на стеке, так что я не уверен имеет ли это хоть какое то влияние…

@Admin, может добавите такое new() для указателей на шаблонные записи? Всё же лучше, если хоть как то работать будет. Может, с предупреждением.

С Наступившими и Наступающими! (и сессия – всегда праздник алсо!)

Думал, что нюансы будут разве что со stringbuilder, однако так и не нашёл пример функции заточенной под .Net для удобной генерации случайной строки, чтобы можно сразу указать алфавит и длину:

 var name:=randomstr('[A-Za-z0-9]',15);

Вроде указывать алфавит через строку - старый (не наш) метод, через диапазоны подобно set of char не очень подходит, т.к. придётся кидать в промежуточный массив, а вот RegEx кажется получше, не?

Либо невнимательно смотрел, либо немного странно, что подобной функции нет в базовой библиотеке PABC аналогично Random/Random2/Random3

1 лайк

Это ожидаемо. Я открою страшную пионерскую тайну: и готового примитива, формирующего целочисленные значения из нескольких диапазонов, тоже нет! Вроде randomint([-5…10,15…30],15). И вообще, страшно подумать, каких только хотелок нет в этом языке)))

Я вот хочу такой интерфейс, чтобы там была такая красивая кнопка, с надписью “Я - величайший программист!”, чтобы щелкнул ее - и сразу окошко раскрывается, а там указываешь реквизиты своего банковского счета и тебе туда - бабах - $1000 за каждый клик падает! ))) Ну вот такая новогодняя хотелка…

@Алекс, и вас с Новогодними) Суть не в невозможном или чрезмерном, а в том как правильно именно для .NET, ведь можно через строку/массивы и комбинировать даже случайные файлы/контент. В общем, для обучающих задач авто/пре/генерация довольно-таки полезная штука, а если чуть серьёзнее, вы относительно правы касательно того же Range.

Спасибо)) Я всего лишь о том, что в свое время пытался обосновать разработчикам свою позицию относительно нехватки различных примитивов. На что мне было сказано насчет принципа разумной достаточности.

Допустим, что несмотря на наличие подобных функций, в базовой библиотеке такое хотя полезно, но не самое главное. Однако какой правильный/одобренный пример для .NET? - вот в чём вопрос.

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

2 лучших способа создать строку - это массивом (у строк есть конструктор для этого) и стринг билдером. Массивом само собой разумеется, а вот стринг билдером:

function RandStr(l: integer; params chars: array of char): string;
begin
  var res := new StringBuilder(l);
  loop l do res += chars[Random(chars.Length)];
  Result := res.ToString;
end;

1 лайк