Program Control_break;

{ Purpose: illustrate the classical CONTROL BREAK problem, where subtotals
  are accumulated for each of several different categories (Employee IDs,
  sales accounts, etc.), after which a grand total of all subtotals is
  given.  The input file must be sorted according to category; when the
  category changes, a "break" occurs and a subtotal is printed.  The 
  technique can be used to any desired degree of nested.                  }

Uses
  Crt;

Type
  Code_num = 100..999;
  Line = String[80];

Const
  Inputfilename = 'NEWSALES.DAT';

Var
  Infile: Text;
  Sales_record: Line;
  Salesperson_number, Previous_number: Code_num;
  Sales_amount, Subtotal, Grandtotal: Real;


{ Procedure #1: Find the salesperson number in sales record St }

Procedure Find_Salesperson_number(St: Line; Var SN: Code_num);


{ Purpose:  St is a string of 80 characters; the first characters in the
            the string are the salesperson number.  Determine this number.
  Input:  St = sales record as read from the input file
  Output: the sales person number is copied from the string and returned
          to the calling program in SN }

Const
  Space = ' ';

Var
  Num: Line;
  Location, Error, Temp: Integer;

Begin
  Location := POS(Space, St);          { locate first space in St }
  Num := COPY(St, 1, Location - 1);    { Num is all chars in St up to 1st space }
  Val(Num, Temp, Error);               { Temp is numeric value of Num }
  If Error > 0
    Then Writeln('Conversion error at ', Error)
    Else SN := Temp;                   { SN = salesperson number }
End;


{ Procedure #2: Find the sales amount at end of sales record St }

Procedure Find_sales_amount(St: Line; Var Sales: Real);


{ Purpose:  St is a string of 80 characters; the final characters in the
            the string are the amount of sales.  Determine this number.
  Input:  St = sales record as read from the input file
  Output: the sales amount is copied from the string and returned
          to the calling program in Sales }

Const
  Decimal_pt = '.';
  Space = ' ';
  Comma = ',';


Var
  Location, Error: Integer;
  R_St: Line;

Begin
  Location := POS(Decimal_pt, St);     { find decimal point in sales amount in St }

  While St[Location] <> Space Do       { back up to first space before decimal pt }
    Location := PRED(Location);

  R_st := COPY(St, Location, Length(St));  { copy sales amount string to R_st }

  Location := POS(Comma, R_st);        { find comma in R_st }
  If Location > 0                      { if comma found, remove it }
    Then Delete(R_st, Location, 1);

  Val(R_st, Sales, Error)              { convert R_st to real value in Sales }

End;

Begin { MAIN }
  Clrscr;


  { Open input file, initialize grand total of all sales, and print
    report header to output file }

  Assign(Infile, Inputfilename);
  Reset(Infile);
  Grandtotal := 0.0;

  Writeln('Salesperson', 'Sales' :10, 'Totals' :20);
  Writeln('==========================================');


  { Process the first line of the input file:

    a) read a sales record from the input file
    b) find the salesperson number from the record; put in Salesperson_number
    c) record this number in Previous_number; when the salesperson number
       changes, this change will be detected by comparison to Previous_number
    d) find the sales amount for this salesperson; put in Sales_amount
    e) initialize Subtotal }

  If NOT EOF(Infile)
    Then
      Begin
        Readln(Infile, Sales_record);
        Find_Salesperson_number(Sales_record, Salesperson_number);
        Previous_number := Salesperson_number;
        Find_sales_amount(Sales_record, Sales_amount);
        Writeln(Salesperson_number, Sales_amount :18:2);
        Subtotal := Sales_amount;
      End;



   While NOT EOF(Infile) Do
     Begin


       { Read next sales record, determine salesperson number, and
         corresponding sales amount }

       Readln(Infile, Sales_record);
       Find_Salesperson_number(Sales_record, Salesperson_number);
       Find_sales_amount(Sales_record, Sales_amount);


       { If salesperson number has not changed, then process sales for
         this salesperson (update sales total) and print salesperson
         number and amount of sales in output }

       If Salesperson_number = Previous_number
         Then
           Begin
             Subtotal := Subtotal + Sales_amount;
             Write(Salesperson_number);
             Writeln(Sales_amount :18:2)
           End
         Else
           Begin

             { This is the "control break".  The salesperson number has
               changed, so the printing of information for the previous
               salesperson is complete; "break" such output and print the
               subtotal for that salesperson.  Update Grand total.  Record
               the new salesperson number in Previous_number.  Write a new
               detail line for new salesperson and sales amount. }

             Writeln;
             Writeln('Subtotal: ', Subtotal :32:2);
             Writeln;
             Grandtotal := Grandtotal + Subtotal;
             Subtotal := Sales_amount;
             Previous_number := Salesperson_number;
             Write(Salesperson_number);
             Writeln(Sales_amount :18:2)
           End
     End;

  Close(Infile);


  { When we leave the WHILE loop, the last subtotal has not yet been
    printed, because there was no opportunity to change the salesperson
    number.  Print the last salesperson's sales subtotal, update the
    grand total, and print the grand total of all sales }

  Writeln;
  Writeln('Subtotal: ', Subtotal :32:2);
  Grandtotal := Grandtotal + Subtotal;
  Writeln;
  Writeln('TOTAL SALES: ', Grandtotal :29:2);
  Readln
End.

-------------------------------------------------
INPUT FILE:  NEWSALES.DAT
-------------------------------------------------

111          3/26/96       G28      1,292.49
111         10/10/96       G66      1,470.57
121          9/21/96       M71        558.89
121           1/5/96       I48      1,199.72
121         10/27/96       Q75        551.87
155          8/27/96       G39      1,749.14


-------------------------------------------------
SCREEN OUTPUT FROM PROGRAM RUN:
-------------------------------------------------

Salesperson     Sales              Totals
==========================================
111           1292.49
111           1470.57

Subtotal:                          2763.06

121            558.89
121           1199.72
121            551.87

Subtotal:                          2310.48

155           1749.14

Subtotal:                          1749.14

TOTAL SALES:                       6822.68