Vanilla_Fury

laba_5_2_del_v3

Apr 11th, 2021
455
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 16.20 KB | None | 0 0
  1. unit laba_5_2_f1;
  2.  
  3. interface
  4.  
  5. uses
  6.   Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  7.   Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Menus, Vcl.StdCtrls, System.RegularExpressions,
  8.   Vcl.ExtCtrls, Vcl.ComCtrls, System.UITypes, Math, MyTree;
  9.  
  10. type
  11.     TArrStr = Array of String;
  12.  
  13.     TFormMain = class(TForm)
  14.     MainMenu1: TMainMenu;
  15.     NHelp: TMenuItem;
  16.     NAuthor: TMenuItem;
  17.     OpenDialog1: TOpenDialog;
  18.     NFile: TMenuItem;
  19.     NOpen: TMenuItem;
  20.     NSaveAs: TMenuItem;
  21.     SaveDialog1: TSaveDialog;
  22.     NSave: TMenuItem;
  23.     NTask: TMenuItem;
  24.     MemoOutput: TMemo;
  25.     ButtonAccept: TButton;
  26.     LabelAnswer: TLabel;
  27.     BalloonHint1: TBalloonHint;
  28.     LabelToMeasureScreenOfUser: TLabel;
  29.     MemoInputCodes: TMemo;
  30.     procedure NAuthorClick(Sender: TObject);
  31.     procedure NOpenClick(Sender: TObject);
  32.     procedure NSaveAsClick(Sender: TObject);
  33.     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  34.     procedure FormCreate(Sender: TObject);
  35.     procedure NSaveClick(Sender: TObject);
  36.     procedure NTaskClick(Sender: TObject);
  37.     function MultPixels(PixQuant: Integer) : Integer;
  38.     procedure MemoInputChange(Sender: TObject);
  39.     procedure ButtonAcceptClick(Sender: TObject);
  40.     procedure OutputAnswer(MyTree: TMyTree);
  41.  
  42.     private
  43.         MultPix: Single;
  44.         StrFile: String;
  45.         IsSaved: Boolean;
  46.     public
  47.  
  48.     end;
  49.  
  50. const
  51.     RegExForNumber = '[1-9]\d{0,2}';
  52.     CaptionHereWillBeAnswer = 'Здесь будет ответ';
  53.  
  54. var
  55.     FormMain: TFormMain;
  56.  
  57. implementation
  58. {$R *.dfm}
  59.  
  60. function FindRegEx(SInput, StrRegEx: String; StrIfNothingFound: String = '') : TArrStr; forward;
  61.  
  62.  
  63. //******************************************************************************
  64. // Ввод данных
  65.  
  66. procedure TFormMain.MemoInputChange(Sender: TObject);
  67. var
  68.     Strs: TArrStr;
  69.     StrOneNumber, TextTemp: String;
  70.     i, SelStartTemp: Integer;
  71.     HasSpaceAtTheEnd: Boolean;
  72.     Point: TPoint;
  73.  
  74. begin
  75.     TextTemp := '';
  76.     with Sender as TMemo do
  77.     begin
  78.         HasSpaceAtTheEnd := (Length(Text) > 0) and
  79.             ((Text[High(Text)] = ' ') or (Text[High(Text)] = #10));
  80.         SelStartTemp := SelStart;
  81.         Strs := FindRegEx(Text, '\d+');
  82.  
  83.         if Length(Strs) > 999 then
  84.         begin
  85.             SetLength(Strs, 999);
  86.             BalloonHint1.Title := 'Предупреждение';
  87.             BalloonHint1.Description := 'Максисальное количество чисел - 999';
  88.             Point.X := Round(Width * 2 / 3);
  89.             Point.Y := Height;
  90.             Balloonhint1.ShowHint(ClientToScreen(Point));
  91.         end;
  92.  
  93.         for i := 0 to High(Strs) do
  94.         begin
  95.             StrOneNumber := FindRegEx(Strs[i], RegExForNumber)[0];
  96.             TextTemp := TextTemp + StrOneNumber;
  97.             if i <> High(Strs) then
  98.                 TextTemp := TextTemp + ' ';
  99.         end;
  100.  
  101.         if HasSpaceAtTheEnd then
  102.                 TextTemp := TextTemp + ' ';
  103.  
  104.         if Text <> TextTemp then
  105.         begin
  106.             if Text <> TextTemp + ' ' then
  107.             begin
  108.                 BalloonHint1.Title := 'Предупреждение';
  109.                 BalloonHint1.Description := 'Разрешены только целые числа от 1 до 999.';
  110.                 Point.X := Round(Width * 2 / 3);
  111.                 Point.Y := Height;
  112.                 Balloonhint1.ShowHint(ClientToScreen(Point));
  113.             end;
  114.  
  115.             Text := TextTemp;
  116.             SelStart := SelStartTemp;
  117.         end;
  118.     end;
  119.  
  120.     if MemoInputCodes.Text <> '' then
  121.         ButtonAccept.Enabled := True
  122.     else
  123.         ButtonAccept.Enabled := False;
  124.  
  125.     NSaveAs.Enabled := False;
  126.     NSave.Enabled := False;
  127.  
  128.     MemoOutput.Text := CaptionHereWillBeAnswer;
  129. end;
  130.  
  131. procedure TFormMain.ButtonAcceptClick(Sender: TObject);
  132. var
  133.     StrsMemoInput: TArrStr;
  134.     Str: String;
  135.     MyTree: TMyTree;
  136.  
  137. begin
  138.     StrsMemoInput := FindRegEx(MemoInputCodes.Text, RegExForNumber);
  139.  
  140.     MyTree.HeadNode := nil;
  141.     for Str in StrsMemoInput do
  142.         AddNodeInTree(MyTree, StrToInt(Str));
  143.  
  144.     OutputAnswer(MyTree);
  145.     NSaveAs.Enabled := True;
  146.     NSave.Enabled := StrFile <> '';
  147. end;
  148.  
  149. //******************************************************************************
  150. // Отрисовка дерева
  151.  
  152. procedure TFormMain.OutputAnswer(MyTree: TMyTree);
  153. var
  154.     HeightOfTree, LineNumber, Margin, Num: Integer;
  155.     NumbersOnLine: TArrInt;
  156.     OneLine: String;
  157.  
  158. begin
  159.     MemoOutput.Clear();
  160.  
  161.     HeightOfTree := CountHeightOfTree(MyTree.HeadNode);
  162.  
  163.     LineNumber := 1;
  164.     Margin := Round(Power(2, HeightOfTree)) - 2;
  165.     while LineNumber < HeightOfTree + 1 do
  166.     begin
  167.         OneLine := '';
  168.         OneLine := OneLine + format(format('%%%ds', [Margin]), ['']);
  169.         NumbersOnLine := GetNumbersOnLine(MyTree.HeadNode, LineNumber);
  170.  
  171.         for Num in NumbersOnLine do
  172.              OneLine := OneLine + format('%3s',
  173.                 [FindRegEx(IntToStr(Num), '[1-9]\d*')[0]]) + format(format('%%%ds',
  174.                 [Margin * 2 + 1]), ['']);
  175.  
  176.         MemoOutput.Lines.Add(OneLine);
  177.         Margin := Round(Margin / 2) - 1;
  178.         Inc(LineNumber);
  179.     end;
  180. end;
  181.  
  182.  
  183. //******************************************************************************
  184. // Работа с файлами
  185.  
  186. procedure TFormMain.NOpenClick(Sender: TObject);
  187. const
  188.     ErrorDuringInputOccured = 'Возникла ошибка при открытии файла.' + #10#13 +
  189.                 'Пожалуйста, выберите файл нужного формата(.datgrad) с ' +
  190.                 'корректными данными.';
  191.  
  192. var
  193.     FileInput : TextFile;
  194.     PathToFile, String1: String;
  195.  
  196. begin
  197.     if not IsSaved and (MessageDlg('Вы хотите сохранить текущие данные?' +
  198.         #10#13 + 'Иначе после открытия файла текущие записи будут удалены.',
  199.         mtConfirmation, [mbYes, mbNo], 0) = mrYes) then
  200.         NSaveClick(Self);
  201.  
  202.     if (IsSaved or (MessageDlg('Вы уверены, что хотите открыть другой файл?' + #10#13 +
  203.         'Все текущие записи будут удалены.', mtConfirmation, [mbYes, mbCancel], 0) = mrYes))
  204.         and OpenDialog1.Execute then
  205.     begin
  206.         PathToFile := OpenDialog1.FileName;
  207.         try
  208.             AssignFile(FileInput, PathToFile);
  209.             Reset(FileInput);
  210.  
  211.             Readln(FileInput, String1);
  212.             MemoInputCodes.Text := String1;
  213.  
  214.             CloseFile(FileInput);
  215.             ButtonAcceptClick(Self);
  216.         except
  217.             ShowMessage(ErrorDuringInputOccured);
  218.         end;
  219.     end;
  220. end;
  221.  
  222. procedure TFormMain.NSaveAsClick(Sender: TObject);
  223. var
  224.     FileOutput : TextFile;
  225.     StrFilePath: String;
  226.     ShouldNotRepeat: Boolean;
  227.     Point: TPoint;
  228.  
  229. begin
  230.     try
  231.         repeat
  232.             ShouldNotRepeat := True;
  233.             if SaveDialog1.Execute then
  234.             begin
  235.                 StrFilePath := SaveDialog1.FileName;
  236.                 StrFilePath := FindRegEx(StrFilePath, '.+\.txt', StrFilePath + '.txt')[0];
  237.  
  238.                 if FileExists(StrFilePath) then
  239.                     if MessageDlg('Такой файл уже существует.' +
  240.                         #10#13 + 'Вы хотите перезаписать файл? Это действие невозможно отменить.',
  241.                         mtConfirmation, [mbYes, mbNo], 0) = mrYes then
  242.                         ShouldNotRepeat := True
  243.                     else
  244.                         ShouldNotRepeat := False
  245.                 else
  246.                     ShouldNotRepeat := True;
  247.  
  248.                 if ShouldNotRepeat then
  249.                 begin
  250.                     AssignFile(FileOutput, StrFilePath);
  251.                     Rewrite(FileOutput);
  252.  
  253.                     Write(FileOutput, 'Введённый список кодов:' + #10#13
  254.                         + MemoInputCodes.Text + #10#13 + 'Ответ:'
  255.                         + #10#13 + MemoOutput.Text + #10#13);
  256.  
  257.                     CloseFile(FileOutput);
  258.                     IsSaved := True;
  259.                     BalloonHint1.Title := 'Готово';
  260.                     BalloonHint1.Description := 'Ответ успешно записан в файл.';
  261.                     Point.X := Round(MemoOutput.Left + MemoOutput.Width * 2 / 3);
  262.                     Point.Y := MemoOutput.Top + MemoOutput.Height;
  263.                     Balloonhint1.ShowHint(ClientToScreen(Point));
  264.  
  265.  
  266.                     NSave.Enabled := True;
  267.                     StrFile := StrFilePath;
  268.                 end;
  269.             end;
  270.         until ShouldNotRepeat;
  271.     except
  272.        ShowMessage('Не удается открыть файл для вывода данных или записать в него данные.');
  273.     end;
  274. end;
  275.  
  276. procedure TFormMain.NSaveClick(Sender: TObject);
  277. var
  278.     FileOutput : TextFile;
  279.  
  280. begin
  281.     if MessageDlg('Вы хотите перезаписать файл "' + StrFile + '"?' + #10#13 +
  282.         'Это действие невозможно отменить.', mtConfirmation, [mbYes, mbNo], 0) = mrYes then
  283.         if FileExists(StrFile) then
  284.         begin
  285.             AssignFile(FileOutput, StrFile);
  286.             Rewrite(FileOutput);
  287.  
  288.             Write(FileOutput, 'Введённый список:' + #10#13
  289.                 + MemoInputCodes.Text + #10#13 + 'Ответ:'
  290.                 + #10#13 + MemoOutput.Text + #10#13);
  291.  
  292.             CloseFile(FileOutput);
  293.             IsSaved := True;
  294.         end
  295.         else
  296.         begin
  297.             ShowMessage('Этого файла уже не существует.');
  298.             StrFile := '';
  299.             NSave.Enabled := False;
  300.             NSaveAsClick(Self);
  301.         end;
  302. end;
  303.  
  304.  
  305. //******************************************************************************
  306. // Form Create
  307.  
  308. procedure TFormMain.FormCreate(Sender: TObject);
  309. begin
  310.     MultPix := LabelToMeasureScreenOfUser.Width / 100;
  311.     StrFile := '';
  312.     IsSaved := True;
  313.     MemoOutput.Text := CaptionHereWillBeAnswer;
  314. end;
  315.  
  316. //******************************************************************************
  317. // Прочее
  318.  
  319. procedure TFormMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  320. begin
  321.     CanClose := IsSaved or (MessageDlg('Вы уверены, что хотите выйти из программы?' +
  322.         #10#13 + 'Все несохранённые данные будут утеряны.',
  323.         mtConfirmation, [mbYes, mbNo], 0) = mrYes);
  324. end;
  325.  
  326. procedure TFormMain.NAuthorClick(Sender: TObject);
  327. begin
  328.     ShowMessage('Панев Александр, гр. 051007' + #10#13 + 'Минск, 2021');
  329. end;
  330.  
  331. procedure TFormMain.NTaskClick(Sender: TObject);
  332. begin
  333.     ShowMessage('Из текстового файла (.TXT) вводится ряд чисел, ' +
  334.     'представляющих собой коды работников фирмы. Первым в этом списке код ' +
  335.     'руководителя фирмы, далее коды его  подчиненных, подчиненных этих ' +
  336.     'подчиненных и т.д.' + #10#13 + 'У каждого сотрудника в непосредственном подчинении ' +
  337.     'может быть не больше двух подчиненных. Если код очередного сотрудника ' +
  338.     'меньше кода его непосредственного начальника, то он располагается ' +
  339.     'слева от своего начальника, иначе справа.');
  340. end;
  341.  
  342. function FindRegEx(SInput, StrRegEx: String; StrIfNothingFound: String = '') : TArrStr;
  343. var
  344.     ArrStr: TArrStr;
  345.     RegEx: TRegEx;
  346.     MatchCollection: TMatchCollection;
  347.     i: Integer;
  348. begin
  349.     RegEx := TRegEx.Create(StrRegEx);
  350.     MatchCollection := RegEx.Matches(SInput);
  351.     SetLength(ArrStr, MatchCollection.Count);
  352.     for i := 0 to MatchCollection.Count - 1 do
  353.         ArrStr[i] := MatchCollection.Item[i].Value;
  354.  
  355.     if (Length(ArrStr) < 1) then
  356.         ArrStr := [StrIfNothingFound];
  357.     Result := ArrStr;
  358. end;
  359.  
  360. function TFormMain.MultPixels(PixQuant: Integer) : Integer;
  361. begin
  362.     Result := Round(PixQuant * MultPix);
  363. end;
  364.  
  365. end.
  366.  
  367.  
  368.  
  369.  
  370.  
  371.  
  372. unit MyTree;
  373.  
  374. interface
  375. uses System.SysUtils, Math;
  376.  
  377. type
  378.     TArrInt = Array of Integer;
  379.  
  380.     PNode = ^TNode;
  381.     TNode = Record
  382.         Number: Integer;
  383.         NextBigger, NextSmaller: PNode;
  384.     End;
  385.     TMyTree = Record
  386.         HeadNode: PNode;
  387.     End;
  388.  
  389.  
  390.     procedure AddNodeInTree(var MyTree: TMyTree; Number: Integer);
  391.     function CountHeightOfTree(HeadNode: PNode) : Integer;
  392.     function GetNumbersOnLine(HeadNode : PNode; LineQuantity: Integer) : TArrInt;
  393.  
  394. implementation
  395.  
  396. procedure AddNodeInTree(var MyTree: TMyTree; Number: Integer);
  397. var
  398.     NewNode, CurrentNode: PNode;
  399.     NextNodesOfCurr: Array[0..1] of PNode;
  400.     ProcessIsNotDone: Boolean;
  401.     Index: Byte;
  402.  
  403. begin
  404.     New(NewNode);
  405.     NewNode.Number := Number;
  406.     NewNode.NextSmaller := nil;
  407.     NewNode.NextBigger := nil;
  408.  
  409.     if MyTree.HeadNode <> nil then
  410.     begin
  411.         ProcessIsNotDone := True;
  412.         CurrentNode := MyTree.HeadNode;
  413.  
  414.         while ProcessIsNotDone do
  415.         begin
  416.             if CurrentNode.Number = Number then
  417.                 ProcessIsNotDone := False
  418.             else
  419.             begin
  420.                 NextNodesOfCurr[0] := CurrentNode.NextSmaller;
  421.                 NextNodesOfCurr[1] := CurrentNode.NextBigger;
  422.                 Index := Ord(Number > CurrentNode.Number);
  423.  
  424.                 if NextNodesOfCurr[Index] <> nil then
  425.                     CurrentNode := NextNodesOfCurr[Index]
  426.                 else
  427.                 begin
  428.                     ProcessIsNotDone := False;
  429.  
  430.                     if Index > 0 then
  431.                         CurrentNode.NextBigger := NewNode
  432.                     else
  433.                         CurrentNode.NextSmaller := NewNode;
  434.                 end;
  435.  
  436.             end;
  437.         end;
  438.     end
  439.     else
  440.     begin
  441.         MyTree.HeadNode := NewNode;
  442.     end;
  443. end;
  444.  
  445. function CountHeightOfTree(HeadNode: PNode) : Integer;
  446. var
  447.     HeightOfTree, HeightFromLeft, HeightFromRight: Integer;
  448.  
  449. begin
  450.     HeightOfTree := 0;
  451.  
  452.     if HeadNode <> nil then
  453.     begin
  454.         HeightFromLeft := 0;
  455.         HeightFromRight := 0;
  456.  
  457.         if HeadNode.NextSmaller <> nil then
  458.             HeightFromLeft := CountHeightOfTree(HeadNode.NextSmaller);
  459.         if HeadNode.NextBigger <> nil then
  460.             HeightFromRight := CountHeightOfTree(HeadNode.NextBigger);
  461.  
  462.         HeightOfTree := Max(HeightFromRight, HeightFromLeft) + 1;
  463.     end;
  464.  
  465.     Result := HeightOfTree;
  466. end;
  467.  
  468. function GetNumbersOnLine(HeadNode : PNode; LineQuantity: Integer) : TArrInt;
  469. var
  470.     NumbersOnLine, NumbersOnLineFromLeft, NumbersOnLineFromRight: TArrInt;
  471.     i: Integer;
  472.  
  473. begin
  474.     SetLength(NumbersOnLine, Round(Power(2, LineQuantity - 1)));
  475.     if LineQuantity = 1 then
  476.         NumbersOnLine[0] := HeadNode.Number
  477.     else
  478.     begin
  479.         if HeadNode.NextSmaller <> nil then
  480.             NumbersOnLineFromLeft := GetNumbersOnLine(HeadNode.NextSmaller, LineQuantity - 1)
  481.         else
  482.         begin
  483.             SetLength(NumbersOnLineFromLeft, Round(Power(2, LineQuantity - 2)));
  484.             for i := Low(NumbersOnLineFromLeft) to High(NumbersOnLineFromLeft) do
  485.                 NumbersOnLineFromLeft[i] := 0;
  486.         end;
  487.  
  488.         if HeadNode.NextBigger <> nil then
  489.             NumbersOnLineFromRight := GetNumbersOnLine(HeadNode.NextBigger, LineQuantity - 1)
  490.         else
  491.         begin
  492.             SetLength(NumbersOnLineFromLeft, Round(Power(2, LineQuantity - 2)));
  493.             for i := Low(NumbersOnLineFromRight) to High(NumbersOnLineFromRight) do
  494.                 NumbersOnLineFromRight[i] := 0;
  495.         end;
  496.  
  497.         for i := Low(NumbersOnLineFromLeft) to High(NumbersOnLineFromLeft) do
  498.             NumbersOnLine[i] := NumbersOnLineFromLeft[i];
  499.         for i := Low(NumbersOnLineFromRight) to High(NumbersOnLineFromRight) do
  500.             NumbersOnLine[i + Length(NumbersOnLineFromLeft)] := NumbersOnLineFromRight[i];
  501.     end;
  502.     Result := NumbersOnLine;
  503. end;
  504. end.
Advertisement
Add Comment
Please, Sign In to add comment