Vanilla_Fury

laba_5_2_del_v2

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