Recent

Poll

When building own project - Finding Libraries, adding them to project and solving dependencies is EASY!!

Yes, it is - never searched for help.
6 (42.9%)
It takes just some minutes to solve or find a solution.
5 (35.7%)
It takes time, but not so much to raise a problem. Ready answers available instantly
2 (14.3%)
It takes time: I spend more then 2 hours/per week communicating on the forum, and asking colegues.
0 (0%)
No, could not use some libraries because of unsolved question.
1 (7.1%)

Total Members Voted: 14

Voting closed: November 29, 2018, 09:29:44 am

Author Topic: Lazarus SinglePoint Help and Internals for NewBies [HELP and PARTICIPATE]  (Read 10781 times)

Researching

  • Full Member
  • ***
  • Posts: 121
Re: Lazarus SinglePoint Help and Internals for NewBies [HELP and PARTICIPATE]
« Reply #15 on: November 28, 2018, 08:13:23 pm »
Nice reply! Grateful!!

Next question... [SOLVED]:
How to sync declaration and implementation "HEADER" of function/procedure:
Ctrl+Shift+C ( gratefully - to Lucamar - see next reply)


« Last Edit: November 28, 2018, 09:40:25 pm by Researching »

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Lazarus SinglePoint Help and Internals for NewBies [HELP and PARTICIPATE]
« Reply #16 on: November 28, 2018, 08:30:51 pm »
A key-shortcut to add function declaration to the interface section.

Have you tried Shift+Ctrl+C? Should work both ways: interface to implementation and viceversa. And if you change the method signature (in either of them) Shift+Ctrl+C will synch the other to the new signature.
« Last Edit: November 28, 2018, 08:33:21 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

Researching

  • Full Member
  • ***
  • Posts: 121
Re: Lazarus SinglePoint Help and Internals for NewBies [HELP and PARTICIPATE]
« Reply #17 on: December 04, 2018, 03:39:29 pm »
Question: // Any help and/or advice appreciated
There are three basic file types in ObjPascal and several separate routines. But most actual operations are done in fixed combinations. I wonder if there is a user library, which handles them all correctly and easy to access?? Or rather should I make it myself?

General concept: Text files:
In real life, at run-time the program generally operates not with "file itself", but with a variable, containing the content of file.
So actually you make changes to the variable and around it just READ and WRITE to file.
I'd like ask for little help to make (if not exists already ) a library, to abstract from thinking about file operations each time.
// Similar for typed and untyped files //

Code: Pascal  [Select][+][-]
  1. {
  2. All operations should be done on transaction basis: with a check if operation finished successfully.
  3. i.e. write to file:
  4.  
  5. 1. Calculate v_ProbableFileSize:= ProbableNewFileSize(
  6.                                                         fContentStrings:string; size:integer)
  7. 2. if (fileAnyExistsCheck(fName))
  8.                ShowMessage ('do you want to replace old file?'); read(updateFile);
  9. 3. if (UpdateFile='Y') create a new file fCreateNew(fName+'_new'); // assign > rewrite
  10. 4. write fContentStrings to fName_new_Handle ->save ->close
  11. 5. if (not CheckSize( fName_new, v_ProbableFileSize) then begin
  12.        rename('fName_new', 'fName_error');
  13.        result := FALSE; // file create, read NOT successful
  14.     end else begin
  15.        rename('fName','fName_bckp');  //old file to backup  
  16.        rename('fName_new', 'fName');  //new file to working file
  17.        result := true; // file create, read successful
  18.     end;
  19. end;
  20. }
  21. unit uFileWorks;
  22. uses {....}
  23. interface
  24. var  
  25.     fileWorks = record
  26.           update:bool;//init :=0;
  27.           keepBckp:ineger;
  28.               //0=>infinite, 1..inf =>number of backups,
  29.               //if>1 - then rename with counter
  30.           postfix_Bckp:string; //
  31.           postfix_Temp:string;//
  32.           postfix_New:string;  //      
  33.    end;
  34.  
  35. function    fileAnyExistsCheck() :boolean;
  36. function    fileAnyDelete()         :boolean;
  37. function    fileTextCreate(fPath:string; fName:string) :boolean;
  38. function    fileTextCreate(fPath:string; fName:string) :boolean;
  39. procedure fileTextStringLinesWrite (
  40.                             FileContent_s:string; fPath:string; fName:string );
  41. procedure fileTextStringLinesRead  (
  42.                             FileContent_s:string; fPath:string; fName:string );
  43. function    fileTextCreate(
  44.                             FileContent_s:string; fPath:string; fName:string ) :boolean;
  45.  
  46. implementation
  47. procedure prcdI_FileWriteTextLines255(
  48.                              s: string; filePath: string; fileName: string ) ;
  49. var
  50.    vL_fHandle:text;
  51.    vL_fName:string;
  52.    i_for:integer;
  53. begin
  54.   //TODO: combine FName + FPath
  55.     if ( filePath ='' )then begin
  56.        vL_fName:=fileName;
  57.     end //END <IF>
  58.     else begin
  59.         vL_fName:=filePath+'\'+fileName; { TODO: update delimiter to crossplatform }
  60.     end; // END<if-else>
  61.   //associate
  62.   Assign(vL_fHandle, vL_fName);
  63.   //Open
  64.   reset(vL_fHandle);
  65.   {writeLines !! Line limited to 255 symbols}
  66.   for i_for:= 1 to Length(s)-1 do
  67.   begin
  68.           case s[i] of
  69.            '#13+#10' :Writeln();
  70.            '#13'     :Writeln();
  71.            '#10'     :Writeln();
  72.           else
  73.             Write(s[i]);
  74.           end;
  75.   end; //END <FOR>
  76.   close(vL_fHandle);
  77.   //TODO: check if fileWrite successful -> transaction
  78. end;                  
  79.  

Researching

  • Full Member
  • ***
  • Posts: 121
Re: [SOLVED] Lazarus UNIT FILE TEMPLATE [HELP and PARTICIPATE]
« Reply #18 on: December 04, 2018, 03:46:33 pm »
The unit file template is generally hard-coded...
But yet user can modify it:
Download the attachment, unpack and replace the original file in the C:\lazarus\components\ideintf
Then rebuild the Lazarus IDE.
Made on Laz 1.8.4

** as usual - "I take no responsibility for any consequence with this topic or file, aside what I do myself on my own computer. All what you do is your own responsibility".

Probably this file is no use for experienced programmers, but may provide some sense to newbies.

Handoko

  • Hero Member
  • *****
  • Posts: 5151
  • My goal: build my own game engine using Lazarus
Re: Lazarus SinglePoint Help and Internals for NewBies [HELP and PARTICIPATE]
« Reply #19 on: December 04, 2018, 06:35:22 pm »
General concept: Text files:

Maybe I don't really understand what you want. I think you're reinventing the wheel. I ever created my own database unit, it has basic saving, loading and sorting ability. It uses OOP concept and very easy to use. But no matter how I tried to optimize the code, the performance is still very poor.

Lazarus is very powerful, it has (almost) all the things you need.

If you want to create file that stores record type data, try this tutorial:
http://www.pascal-programming.info/lesson11.php#jump5

If you want to create file that stores text data you can use the old school read/write, see my demo:
http://forum.lazarus.freepascal.org/index.php/topic,37766.msg254800.html#msg254800

But storing text file is easier if you use TStringList:
http://wiki.freepascal.org/TStringList-TStrings_Tutorial

For untyped binary data, you can use TFileStream or the classic blockread/blockwrite:
http://wiki.freepascal.org/TFileStream

But if performance is important, you should consider to use a database. TDbf probably is the easiest but it lacks of many enterprise-level features.
http://wiki.lazarus.freepascal.org/Databases

That's all I can remember for now, actually it has more than what I have mentioned above.

And for basic file operations (file exists, delete, rename) or old procedural style file handling, read here:
https://www.freepascal.org/docs-html/rtl/sysutils/index-5.html
http://wiki.freepascal.org/fileutil
http://wiki.freepascal.org/File_Handling_In_Pascal

Quote
The idea: Abstract from small file routines to the direction of dynamic/ functional programming:
You just write like a question/SQL request :

FileLineByNumberGet
FileLineByMarkerGet
FileLineByContentGet
FileLineByNumberDelete
FileLineByNumberInsert
FileLineByMarkerInsert
FileLineByContentInsert

Supposition is: this may speedup the development of all applications,
since this will make easier to test the code (run with params from file and write output to file)

The idea may sound good but I don't think it is good. Use TStringList instead, it is written by professional, fully tested, optimized and maintained. No need to reinvent the wheel. In your idea, the file is opened and closed each time you call a function. TStringList is faster because it is kept in the memory until you free it and the data will be saved to disk only if you tell it to do so.
https://www.freepascal.org/docs-html/rtl/classes/tstringlist.html

I think it should be like this:
FileLineByNumberGet     -> TStringList[index]
FileLineByMarkerGet     -> ?
FileLineByContentGet    -> ?
FileLineByNumberDelete  -> TStringList.Delete(index)
FileLineByNumberInsert  -> TStringList.Insert(index, S)
FileLineByMarkerInsert  -> ?
FileLineByContentInsert -> ? maybe TStringList.Add(S)


But if it is for learning purpose, I agree you should write the module. As I've already learned to write my own database (although it is ugly). :D
« Last Edit: December 04, 2018, 06:37:40 pm by Handoko »

Researching

  • Full Member
  • ***
  • Posts: 121
Re: Lazarus SinglePoint Help and Internals for NewBies [HELP and PARTICIPATE]
« Reply #20 on: December 05, 2018, 09:53:29 am »
Hi, Handoko! This is great stuff to read!
Having a "File of records" - humanly read - is the actual need.
Questions:
Open/close operations seem to be ultimate for correct file handling. ( without %close%  data might be left in memory, rather than written to disk). So maybe %close% must be put into %finalize% section.
But still!! in my case (if not mistaken), there is a need to abstract file operations. So probably this work have to get done.
The performance question: work with variable as long as you do not need writing to disk. When need writing to disk - do it clearly with a set of procedures:
fileText%DoWhat%();
The only question, I did not yet find ready done is: clear blocks of operations for main file types.
Going to search again.
Good day to you!

>>
Had a hope to find useful things in Laz sources - could not...
Trying to search for blocks of:
Assign / Open / read(write)/close
For each main type of file.
Using records to write a file would be even better...
## After try: No, file of records is not manually editable.
## need to have a file with manual access - edit in textMode, use in program.
Need to make:
Write::= if (exists) {ask} else{Assign+Open+write+close}
Read::= try {Assign+Open+write+close} finally {'not found'}
And yes --- for console mode[\u]
« Last Edit: December 05, 2018, 10:37:39 am by Researching »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11447
  • FPC developer.
Re: Lazarus SinglePoint Help and Internals for NewBies [HELP and PARTICIPATE]
« Reply #21 on: December 05, 2018, 11:35:37 am »
Note that such schemes limit the size of the file you can process.  Multi layer blue ray images somebody ? (easily 15-25GB+)

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Lazarus SinglePoint Help and Internals for NewBies [HELP and PARTICIPATE]
« Reply #22 on: December 05, 2018, 02:53:19 pm »
But still!! in my case (if not mistaken), there is a need to abstract file operations.

Use strreams. FPC/Lazarus have quite a lot of descendants of TStream and you can always add your own.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

Researching

  • Full Member
  • ***
  • Posts: 121
Re: Lazarus SinglePoint Help and Internals for NewBies [HELP and PARTICIPATE]
« Reply #23 on: December 06, 2018, 01:19:39 pm »
Final conclusion: need to build
1. a new file type "from zero"- from char/byte level; a data structure and associated operations.
I will be human readable txt, searchable, with "calculated" positions.
Unlimited line size
Corresponding VariableType : StructText; - to handle reads from file.
Probably - the first 1..2 lines of file - will be a heading - file map.
Easy insertion / deletion. Most procedures abstracted to the level Read / search / edit / write.
Actually it resembles SQL and XML capabilities, but! with simplicity of procedural operations.

Questions:
which data structures (list/queue/FIFO...) and basic operations to use and learn,
where to find the implementation of standard file types in the IDE source to learn?

2. Need a template of
TestExecuteEXEWithParams('InputParams', 'program.EXE', 'outputFile.txt' )
Any help?

//Yes many solutions exist like StringList, TString .... etc. But at this moment - need what stated.
On other side, if someone can give arguments, about impossibility of this task - would be great.

//side question: How to procedurally (console mode) handle text lines longer than 255? Imagine - console mode text editor....
Should I look to the direction of :file of byte ?
« Last Edit: December 06, 2018, 01:22:29 pm by Researching »

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Lazarus SinglePoint Help and Internals for NewBies [HELP and PARTICIPATE]
« Reply #24 on: December 06, 2018, 01:47:30 pm »
//side question: How to procedurally (console mode) handle text lines longer than 255?

Use AnsiString instead of String[], or directly add {$H+} or {$LONGSTRINGS ON} to your source.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

Handoko

  • Hero Member
  • *****
  • Posts: 5151
  • My goal: build my own game engine using Lazarus
Re: Lazarus SinglePoint Help and Internals for NewBies [HELP and PARTICIPATE]
« Reply #25 on: December 06, 2018, 02:00:55 pm »
I will be human readable txt, searchable, with "calculated" positions.
Unlimited line size

You maybe need Rope:
http://forum.lazarus.freepascal.org/index.php/topic,42957

2. Need a template of
TestExecuteEXEWithParams('InputParams', 'program.EXE', 'outputFile.txt' )

Read here:
http://wiki.freepascal.org/Executing_External_Programs

//side question: How to procedurally (console mode) handle text lines longer than 255? Imagine - console mode text editor....

Use TStringList or TMemoryStream
« Last Edit: December 06, 2018, 02:02:38 pm by Handoko »

Researching

  • Full Member
  • ***
  • Posts: 121
Re: Lazarus SinglePoint Help and Internals for NewBies [HELP and PARTICIPATE]
« Reply #26 on: December 22, 2018, 06:39:27 am »
Handoko, Ropes are great, but not yet for my brain.
Now I'm back with next question.

How to implement read/write (fHandle, ArrayOfRecord).
The question is actually about Enumeration:
Is it available in console mode? Or GUI mode only?

Code: Pascal  [Select][+][-]
  1. type
  2.     tRec_Node = record
  3.           ID, x, y  
  4.               : integer;
  5.          Name, Description, members
  6.                : string;
  7. end;
  8. var
  9.      NodeList : array of tRec_Node;
  10. begin
  11.    fnctWriteArrRecToFile(fHandle, NodeList );
  12.    fnctReadArrRecOfFile(fHandle, NodeList );
  13. end.

If the array would be same structured and RAM-light, would do like:
Code: Pascal  [Select][+][-]
  1. For i:=0 to length (Arr1) do
  2.    For vString in Arr1[i] do begin
  3.       read/write (fHandle, vString +vFieldDelim);
  4.       writeln();
  5.    end;

so how to prepare and use for ... in .... do with Array of Records?

Handoko

  • Hero Member
  • *****
  • Posts: 5151
  • My goal: build my own game engine using Lazarus
Re: Lazarus SinglePoint Help and Internals for NewBies [HELP and PARTICIPATE]
« Reply #27 on: January 05, 2019, 02:03:09 pm »
Sorry, I was busy recently. Now,  I have some time to write a demo.

I don't fully understand your problem, below is an example showing how to do binary file reading, adding and deleting record. It does not use for-in. If you want to learn about how to use for-in, you can read the documentation here:
http://wiki.lazarus.freepascal.org/for-in_loop

Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   {$IFDEF UNIX}{$IFDEF UseCThreads}
  7.   cthreads,
  8.   {$ENDIF}{$ENDIF}
  9.   Classes, Crt, sysutils
  10.   { you can add units after this };
  11.  
  12. type
  13.   TData = packed record
  14.     ID      : Integer;
  15.     Age     : Byte;
  16.     Name    : string[20];
  17.     Address : string[30];
  18.   end;
  19.  
  20. var
  21.   Data: array of TData;
  22.  
  23. const
  24.   DataFileName = 'MyData.dat';
  25.  
  26. function ReadLnInteger(ValMin, ValMax: Integer): Integer;
  27. var
  28.   UserInput : Integer;
  29.   S         : string;
  30.   Valid     : Boolean;
  31. begin
  32.   repeat
  33.     Valid := True;
  34.     ReadLn(S);
  35.     if not(TryStrToInt(S, UserInput)) then
  36.       Valid := False;
  37.     if (UserInput < ValMin) or (UserInput > ValMax) then
  38.       Valid := False;
  39.     if not(Valid) then
  40.       WriteLn('Please provide a valid value (' + ValMin.ToString + ' - ' +
  41.         ValMax.ToString + '):');
  42.   until Valid;
  43.   Result := UserInput;
  44. end;
  45.  
  46. function ReadLnString(MaxLength: Integer): string;
  47. var
  48.   S     : string;
  49.   Valid : Boolean;
  50. begin
  51.   repeat
  52.     Valid := True;
  53.     ReadLn(S);
  54.     if (S = '') or (Length(S) > MaxLength) then
  55.       Valid := False;
  56.     if not(Valid) then
  57.     begin
  58.       WriteLn('Maximum ' + MaxLength.ToString + ', empty input is not allowed.');
  59.       WriteLn('Please provide a valid input:');
  60.     end;
  61.   until Valid;
  62.   Result := S;
  63. end;
  64.  
  65. procedure WriteScreen(S: string);
  66. const
  67.   LineNo: Byte = 0;
  68. begin
  69.   if S = 'clrscr' then
  70.   begin
  71.     LineNo := 0;
  72.     Exit;
  73.   end;
  74.   if LineNo <= 0 then
  75.     ClrScr;
  76.   WriteLn(S);
  77.   Inc(LineNo);
  78.   if LineNo > 22 then
  79.   begin
  80.     LineNo := 0;
  81.     ReadKey;
  82.   end;
  83. end;
  84.  
  85. procedure ReadData;
  86. var
  87.   DataFile : File of TData;
  88.   Index    : Integer;
  89. begin
  90.  
  91.   SetLength(Data, 0);
  92.   if not(FileExists(DataFileName)) then
  93.     Exit;
  94.  
  95.   AssignFile(DataFile, DataFileName);
  96.   Reset(DataFile);
  97.   Index := 0;
  98.   while not(EOF(DataFile)) do
  99.   begin
  100.     SetLength(Data, Index+1);
  101.     Read(DataFile, Data[Index]);
  102.     Inc(Index);
  103.   end;
  104.   CloseFile(DataFile);
  105.  
  106. end;
  107.  
  108. procedure SaveData;
  109. var
  110.   DataFile : File of TData;
  111.   i        : Integer;
  112. begin
  113.   AssignFile(DataFile, DataFileName);
  114.   Rewrite(DataFile);
  115.   for i := 0 to High(Data) do
  116.     Write(DataFile, Data[i]);
  117.   CloseFile(DataFile);
  118. end;
  119.  
  120. procedure MenuShow;
  121. var
  122.   i: Integer;
  123. begin
  124.  
  125.   ClrScr;
  126.   if Length(Data) <= 0 then
  127.   begin
  128.     WriteLn('Nothing to show.');
  129.     ReadKey;
  130.     Exit;
  131.   end;
  132.  
  133.   WriteScreen('clrscr');
  134.   WriteScreen('=== Data File : ' + DataFileName + ' === Total : ' +
  135.     Length(Data).ToString + ' record ===');
  136.   WriteScreen('');
  137.   for i := 0 to High(Data) do
  138.   begin
  139.     WriteScreen('  Record #'   + (i+1).ToString);
  140.     WriteScreen('  ID      : ' + Data[i].ID.ToString);
  141.     WriteScreen('  Age     : ' + Data[i].Age.ToString);
  142.     WriteScreen('  Name    : ' + Data[i].Name);
  143.     WriteScreen('  Address : ' + Data[i].Address);
  144.     WriteScreen('');
  145.   end;
  146.   WriteScreen('Press any key to go to the main menu ...');
  147.   ReadKey;
  148.  
  149. end;
  150.  
  151. procedure MenuAdd;
  152. var
  153.   CurrentData : TData;
  154.   C           : Char;
  155. begin
  156.  
  157.   ClrScr;
  158.   Write('ID = ');
  159.   CurrentData.ID      := ReadLnInteger(0, 9999);
  160.   Write('Age = ');
  161.   CurrentData.Age     := ReadLnInteger(0, 150);
  162.   Write('Name = ');
  163.   CurrentData.Name    := ReadLnString(SizeOf(CurrentData.Name));
  164.   Write('Address = ');
  165.   CurrentData.Address := ReadLnString(SizeOf(CurrentData.Address));
  166.   ClrScr;
  167.   WriteLn('ID      : ' + CurrentData.ID.ToString);
  168.   WriteLn('Age     : ' + CurrentData.Age.ToString);
  169.   WriteLn('Name    : ' + CurrentData.Name);
  170.   WriteLn('Address : ' + CurrentData.Address);
  171.   WriteLn;
  172.   WriteLn('Save the data? [y/n]');
  173.  
  174.   repeat
  175.     C := ReadKey;
  176.     case C of
  177.       'n', 'N' : Exit;
  178.       'y', 'Y' :
  179.         begin
  180.           SetLength(Data, Length(Data)+1);
  181.           Data[High(Data)] := CurrentData;
  182.           SaveData;
  183.           Exit;
  184.         end;
  185.     end;
  186.   until False;
  187.  
  188. end;
  189.  
  190. procedure MenuDelete;
  191. var
  192.   RecordNo : Integer;
  193.   C        : Char;
  194.   i        : Integer;
  195. begin
  196.  
  197.   ClrScr;
  198.   if Length(Data) <= 0 then
  199.   begin
  200.     WriteLn('Nothing to delete.');
  201.     ReadKey;
  202.     Exit;
  203.   end;
  204.  
  205.   WriteLn('Please provide the record no of the data you want to delete:');
  206.   RecordNo := ReadLnInteger(1, Length(Data));
  207.   WriteLn;
  208.   WriteLn('  Record #'   + (RecordNo).ToString);
  209.   WriteLn('  ID      : ' + Data[RecordNo-1].ID.ToString);
  210.   WriteLn('  Age     : ' + Data[RecordNo-1].Age.ToString);
  211.   WriteLn('  Name    : ' + Data[RecordNo-1].Name);
  212.   WriteLn('  Address : ' + Data[RecordNo-1].Address);
  213.   WriteLn;
  214.   WriteLn('Delete the data? [y/n]');
  215.  
  216.   repeat
  217.     C := ReadKey;
  218.     case C of
  219.       'n', 'N' : Exit;
  220.       'y', 'Y' :
  221.         begin
  222.           for i := 1 to High(Data) do
  223.             if i >= RecordNo then
  224.               Data[i-1] := Data[i];
  225.           SetLength(Data, Length(Data)-1);
  226.           SaveData;
  227.           Exit;
  228.         end;
  229.     end;
  230.   until False;
  231.  
  232. end;
  233.  
  234. procedure MenuMain;
  235. var
  236.   Selected: Char;
  237. begin
  238.   repeat
  239.     ClrScr;
  240.     WriteLn('Welcome to the Pascal Binary File Demo');
  241.     WriteLn;
  242.     WriteLn('Main Menu:');
  243.     WriteLn('1 - Show data');
  244.     WriteLn('2 - Add data');
  245.     WriteLn('3 - Delete data');
  246.     WriteLn('x - Exit');
  247.     WriteLn;
  248.     Selected := ReadKey;
  249.     case Selected of
  250.       '1': MenuShow;
  251.       '2': MenuAdd;
  252.       '3': MenuDelete;
  253.       'x', #27: Exit;
  254.     end;
  255.   until False;
  256. end;
  257.  
  258. begin
  259.   ReadData;
  260.   MenuMain;
  261.   ClrScr;
  262. end.

If you prefer simpler demo, you can try this tutorial:
http://www.pascal-programming.info/lesson11.php#jump5

 

TinyPortal © 2005-2018