home *** CD-ROM | disk | FTP | other *** search
/ Jason Aller Floppy Collection / 180.img / TURBOD.ZIP / TPDEMOB.PAS < prev    next >
Pascal/Delphi Source File  |  1989-05-02  |  6KB  |  236 lines

  1. {$N+,E+}
  2.  
  3. (* File: TPDEMOB.PAS
  4.  
  5.    Broken Turbo Pascal Demonstration program to show off Turbo Debugger
  6.  
  7.    Reads words from standard input, analyzes letter and word frequency.
  8.    Uses linked list to store commandline parameters on heap.
  9.  
  10.    Uses the following data types:
  11.  
  12.      Boolean,
  13.      Char, Byte,
  14.      Integer, Word,
  15.      LongInt,
  16.      Extended (8087 type, links in emulator)
  17.      String,
  18.      Array,
  19.      Record,
  20.      Set,
  21.      Pointer
  22.  
  23.   Comments that look like this:
  24.  
  25.     { ** Bug: <description> }
  26.  
  27.   are inserted above lines that contain bugs.
  28.  
  29. *)
  30. program TPDemo;
  31.  
  32. const
  33.   BufSize    = 128;    { length of line buffer }
  34.   MaxWordLen =  10;    { maximum word length allowed }
  35.  
  36. type
  37.   BufferStr = String[BufSize];
  38.  
  39.   LInfoRec = record
  40.     Count : Word;               { number of occurrences of this letter }
  41.     FirstLetter : Word;         { number of times as first letter of a }
  42.   end;
  43.  
  44.  
  45. var
  46.   NumLines, NumWords : Word;                     { counters }
  47.   NumLetters : LongInt;
  48.   WordLenTable : array [1..MaxWordLen] of Word;  { info for each word }
  49.   LetterTable : array['A'..'Z'] of LInfoRec;     { info for each letter }
  50.   Buffer : BufferStr;
  51.  
  52. procedure ShowResults;
  53.  
  54. procedure ShowLetterInfo(FromLet, ToLet : Char);
  55. { Dump letter information }
  56. var
  57.   ch : Char;
  58. begin
  59.   Writeln;
  60.   Write('Letter:     ');
  61.   { ** Bug: Extra semicolon }
  62.   for ch := FromLet to ToLet do;                { column titles }
  63.     Write(ch:5);
  64.   Writeln;
  65.  
  66.   Write('Frequency:  ');
  67.   for ch := FromLet to ToLet do                 { letter count }
  68.     Write(LetterTable[ch].Count:5);
  69.   Writeln;
  70.   Write('Word starts:');
  71.   for ch := FromLet to ToLet do                 { first letter count }
  72.     Write(LetterTable[ch].FirstLetter:5);
  73.   Writeln;
  74. end; { ShowLetterInfo }
  75.  
  76. var
  77.   i : Integer;
  78.   AvgWords : Extended;
  79.  
  80. begin { ShowResults }
  81.   { ** Bug: should test to avoid divide by zero; should be words per line }
  82.   AvgWords := NumLines / NumWords;
  83.   Writeln;
  84.   Writeln(NumLetters, ' char(s) in ',
  85.           NumWords, ' word(s) in ',
  86.           NumLines, ' line(s)');
  87.   Writeln('Average of ', AvgWords:0:2, ' words per line');
  88.   Writeln;
  89.  
  90.   { Dump word count }
  91.   Write('Word length:');
  92.   for i := 1 to MaxWordLen do
  93.     Write(i:4);
  94.   Writeln;
  95.  
  96.   Write('Frequency:  ');
  97.   for i := 1 to MaxWordLen do
  98.     Write(WordLenTable[i]:4);
  99.   Writeln;
  100.  
  101.   { Dump letter counts }
  102.   ShowLetterInfo('A', 'M');
  103.   ShowLetterInfo('N', 'Z');
  104. end; { ShowResults }
  105.  
  106. procedure Init;
  107. begin
  108.   NumLines := 0; NumWords := 0; NumLetters := 0;
  109.   FillChar(LetterTable, SizeOf(LetterTable), 0);
  110.   FillChar(WordLenTable, SizeOf(WordLenTable), 0);
  111.   Writeln('Enter a string to process, an empty string quits.');
  112. end; { Init }
  113.  
  114. procedure ProcessLine(S : BufferStr);
  115.  
  116. function IsLetter(ch : Char) : Boolean;
  117. begin
  118.   { ** Bug: Should shift character to uppercase before testing }
  119.   IsLetter := ch in ['A'..'Z'];
  120. end; { IsLetter }
  121.  
  122. var
  123.   i : Integer;
  124.   WordLen : Word;
  125.  
  126. begin { ProcessLine }
  127.   Inc(NumLines);
  128.   i := 1;
  129.   while i <= Length(S) do
  130.   begin
  131.     { Skip non-letters }
  132.     while (i <= Length(S)) and not IsLetter(S[i]) do
  133.       Inc(i);
  134.  
  135.     { Find end of word, bump letter & word counters }
  136.     WordLen := 0;
  137.     while (i <= Length(S)) and IsLetter(S[i]) do
  138.     begin
  139.       Inc(NumLetters);
  140.       Inc(LetterTable[UpCase(S[i])].Count);
  141.       if WordLen = 0 then                    { bump counter }
  142.         Inc(LetterTable[UpCase(S[i])].FirstLetter);
  143.       Inc(i);
  144.       Inc(WordLen);
  145.     end;
  146.  
  147.     { Bump word count info }
  148.     if WordLen > 0 then
  149.     begin
  150.       Inc(NumWords);
  151.       if WordLen <= MaxWordLen then
  152.         Inc(WordLenTable[WordLen]);
  153.     end;
  154.   end; { while }
  155. end; { ProcessLine }
  156.  
  157. function GetLine : BufferStr;
  158. var
  159.   S : BufferStr;
  160. begin
  161.   Write('String: ');
  162.   Readln(S);
  163.   GetLine := S;
  164. end;
  165.  
  166. procedure ParmsOnHeap;
  167. { Builds a linked list of commandline parameters on the heap.
  168.   Note that the zero'th parameter, ParamStr(0), returns the
  169.   Exec name of the program on Dos 3.xx only.
  170. }
  171. type
  172.   ParmRecPtr = ^ParmRec;
  173.   ParmRec = record
  174.     Parm : ^String;
  175.     Next : ParmRecPtr;
  176.   end;
  177. var
  178.   Head, Tail, Temp : ParmRecPtr;
  179.   i : Integer;
  180.   s : String;
  181. begin
  182.   Head := nil;
  183.   for i := 0 to ParamCount do
  184.   begin
  185.     { Get next commandline parameter }
  186.     s := ParamStr(i);
  187.     if MaxAvail < SizeOf(ParmRec) + Length(s) + 1 then  { room on heap? }
  188.     begin
  189.       Writeln('Heap full, procedure aborting...');
  190.       Exit;
  191.     end;
  192.  
  193.     { Add to linked list }
  194.     New(Temp);                         { another Parm record }
  195.     with Temp^ do
  196.     begin
  197.       { ** Bug: Should allocate enough for length byte }
  198.       GetMem(Parm, Length(s));         { string + length byte }
  199.       Parm^ := s;
  200.       Next := nil;
  201.     end;
  202.     if Head = nil then                 { initialize list pointer }
  203.       Head := Temp
  204.     else
  205.       Tail^.Next := Temp;              { add to end }
  206.     Tail := Temp;                      { update tail pointer }
  207.   end; { for }
  208.  
  209.   { Dump list }
  210.   Writeln;
  211.   with Head^ do
  212.     if Parm^ <> '' then
  213.       Writeln('Program name: ', Parm^);
  214.   Write('Command line parameters: ');
  215.   Tail := Head^.Next;
  216.   while Tail <> nil do
  217.     with Tail^ do
  218.     begin
  219.       Write(Parm^, ' ');
  220.       Tail := Next;
  221.     end;
  222.   Writeln;
  223. end; { ParmsOnHeap }
  224.  
  225. begin { program }
  226.   Init;
  227.   Buffer := GetLine;
  228.   while Buffer <> '' do
  229.   begin
  230.     ProcessLine(Buffer);
  231.     Buffer := GetLine;
  232.   end;
  233.   ShowResults;
  234.   ParmsOnHeap;
  235. end.
  236.