screen I/O pgm

February 10, 2010

this program, in C and Pascal, has a 4 level nested search-repeat parse through a list.

This program was written back in the days of cassette tapes!: Screen I/O pgm in C & Pascal.

This program will go through a list of songs, throwing out one song or another until it finds a total time that most nearly matches the target time. It will display and write to a (text) file the new (sub) list and, separately, the song(s) that it threw out. What was surprising was that with only 1 or 2 extra songs, the program could almost always come within 5 sec. of the exact time!

back in 1985:
GIVEN: that many people enjoy recording their favorite records onto cassette tapes and playing them in their car tape players (as well as home tape decks) and do NOT enjoy the tape coming to the end in the middle of a song.
THEREFORE …

WRITE: A program that prompts for a target time (30:00 min 45:00 min., or even 33:28 min & sec etc.) and then prompts for
1. a number of seconds to be added between songs. (4 is common)
2. a string of about 30 to 35 characters. (a song title)
3. a number between 0 and 9 (minutes) and
4. a number between 0 and 59 (seconds) until only
1 or 2 more than enough to pass the total target time or end-of-data is encountered; whichever comes first.
If EOD is first, terminate the program with a message (not enough data).

The program has been written in Pascal (Borland’s Turbo Pascal) and
in C (compiled by both Borland’s Turbo C and MicroSoft’s C

C

   #include 
   /*-----------------------------------------------------------------*/
   /*              THIS 3RD VERSION  DISPLAYS THE 1ST 20              */
   /*           SOLUTIONS BY DIRECTLY ADDRESSING THE SCREEN           */
   /*-----------------------------------------------------------------*/
   /**------     E X T E R N A L   D E C L A R A T I O N S     ------**/
   #define minimum_minutes  16
   #define maximum_minutes  64
   #define songsLimit   31                   /*  array from  0 to 30  */
   #define titleLength  36                   /*  array from  0 to 35  */
   #define displayLimit 31                   /*  array from  0 to 30  */
   #define total_error_limit 40              /*  seconds from target  */

   FILE *tapelog ;

   int     TargetMinutes,         songs      ;
   int     TargetSeconds,         this_one   ;
   int     ttl_trgt_secs,         this_song  ;
   int     subttl_Minutes,        last_song  =  0 ;
   int     subttl_Seconds = 0,    xtraSongs  =  0 ;
   int     subttl_in_secs = 0,    xtraSeconds = 0 ;
   int     out1,     out3,        limit = 0  ;
   int     out2,     out4,        diff  = 0  ;

   static  char   d_title  [songsLimit]  [titleLength+1] ; /* strings */

           char   *atitle  [songsLimit]  ;   /* pointers to strings */
           char   astring [titleLength]  ;     /* an extra string */
           char   ch ;
           char   test [11] ;

   int     minutes  [songsLimit]  ;
   int     seconds  [songsLimit]  ;
   int     ttlsecs  [songsLimit]  ;
   int     outtime  [songsLimit]  ;

    /*  ---------------+----------------------------------+--------------  */
    /*  ---------------+    B E G I N   P R O G R A M:    +--------------  */
    /*  ---------------+----------------------------------+--------------  */
 main ()
   {
   union REGS  r ;

   printf ("\n\n");
   printf ("\t   +------------------------------------------------------+  \n");
   printf ("\t   |   M A K I N G     A     C A S S E T T E    T A P E   |  \n");
   printf ("\t   +------------------------------------------------------+  \n");
   printf ("\t   Given that we enjoy recording our records onto tapes but  \n");
   printf ("\t   we do NOT enjoy the tape coming to the end in the middle  \n");
   printf ("\t   of a song,  this program enables a person to  . . .       \n\n");
   printf ("\t   Enter a list of songs and their durations (min's & sec's) \n");
   printf ("\t   that total just over a required minimum,  ex: 30 minutes, \n");
   printf ("\t   plus 1 more song.   This program will then go through the \n");
   printf ("\t   list throwing out one song or another,  until it finds a  \n");
   printf ("\t   total time that most nearly matches the target time.   It \n");
   printf ("\t   will then display the results.                            \n");
   printf ("\t   ( p.s.   a 30 min. tape seems to last  31 min. & 30 sec.) \n");
   printf ("\t   (        a 45 min. tape seems to last  46 min. & 30 sec.) \n");
   printf ("\t   (        and  add  about  3 to 6  seconds between songs.) \n\n");
   printf ("\t   Please  enter  the  total  target  time  for  one  side : \n");
   printf ("\t   (between %d & %d min.)                 ( otherwise quit ) \n",
                                    minimum_minutes, maximum_minutes );
   printf ("\t         ( %d to %d )  MINUTES:  ",
                                    minimum_minutes, maximum_minutes );

   gets (astring);
                   /* - - - - - - - - - - - - - - - - - - - - - - - - - */
                   /*    a person normally verifies the data as valid   */
                   /*    before  Ascii TO Integer  conversion (atoi):   */
                   /* - - - - - - - - - - - - - - - - - - - - - - - - - */
   TargetMinutes = atoi (astring);

     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     /*   the program terminates here unless the entry time is valid:   */
     /*          (to be valid, the   target minutes   must be           */
     /*         between  minimum_minutes  and  maximum_minutes)         */
     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

   if ( TargetMinutes >= minimum_minutes  &&
        TargetMinutes  60 )
            printf ("\t      Seconds must be between  0 and 60.  \n");
         }
      while  ( TargetSeconds  60 );

      ttl_trgt_secs = TargetMinutes * 60  +  TargetSeconds ;
      printf ("\t                    Confirmed:  %2d:%02d \n",
                                         TargetMinutes, TargetSeconds);
      printf ("\t   Enter the number of seconds to be added \t\t default=4\n");
      printf ("\t   to the subtotal, between songs:  (0-7): ");
      ch = getch();
      switch ( ch )
            {
            case '0' :  xtraSeconds = 0 ;    break ;
            case '1' :  xtraSeconds = 1 ;    break ;
            case '2' :  xtraSeconds = 2 ;    break ;
            case '3' :  xtraSeconds = 3 ;    break ;
            case '4' :  xtraSeconds = 4 ;    break ;
            case '5' :  xtraSeconds = 5 ;    break ;
            case '6' :  xtraSeconds = 6 ;    break ;
            case '7' :  xtraSeconds = 7 ;    break ;
            default  :  xtraSeconds = 4 ;
            }
         printf ("%1d \n\n", xtraSeconds ) ;

     /* ----------------------------------------------------------- */
     /*                 E N T E R   T H E   D A T A                 */
     /* ----------------------------------------------------------- */
      last_song = 0 ;
                  /*   get the 1st title  and set it   */
                  /*   = to last_song if it verifies   */
      getTitle() ;

      /* - - - - - - - -  main loop  - - - - - - - - - */
      /*     While the title is not null,  the array   */
      /*   limit has not been over-extended,  and we   */
      /*   have not entered more than 2 extra songs,   */
      /* - - - - - - Enter  another song - - - - - - - */

      while ( strlen(d_title[last_song + 1]) != 3
         &&   xtraSongs  %2d:%02d  \n" ,
                   subttl_Minutes, subttl_Seconds ,
                    TargetMinutes,  TargetSeconds );

         if  ( ttl_trgt_secs  1 )
         {
          display_song_list();    /* display on screen */
          /* ------------------------------------------------------------- */
          /*               WRITE  LIST  TO  FILE  (TAPE-LOG)               */
          /* ------------------------------------------------------------- */
         if ( ( tapelog = fopen ( "tape-log", "a") )  != NULL )
            {
             fprintf (tapelog, "\n\n\n ================================ \n" );
             fprintf (tapelog, " --   --  A FULL LISTING  --   -- \n" );
             fprintf (tapelog, " ================================ \n" );
             for ( this_song=1;  this_song  ttl_trgt_secs )
                   diff = outtime[out1] - ttl_trgt_secs ;
                  else
                   diff = ttl_trgt_secs - outtime[out1] ;

                  /* diff  =  abs ( outtime[out1] - ttl_trgt_secs ); */
                if ( diff == limit )   display_songs() ;

                 /* - - - - - - - - - - - - - - - - - - - - - - - - */
                 /****   see if throwing out  2  songs will do   ****/
                 /* - - - - - - - - - - - - - - - - - - - - - - - - */
               for ( out2 = out1+1 ;  out2  1 )  */
      }   /*   if ( TargetMinutes > minimum_minutes  && ...   */
   }  /*  main  */

   /* ------------------------------------------------------------------ */
   /* -------------------  ( E N D     P R O G R A M )  ---------------- */
   /* ------------------------------------------------------------------ */
   /*                                                                    */
   /* ------------------------------------------------------------------ */
   /* --------------  ( B E G I N   S U B R O U T I N E S )  ----------- */
   /* ------------------------------------------------------------------ */

   /* ------------------------------------------------------------------ */

      r.h.ah = 15 ;  /* gets video mode */
      vmode = int86(0x10, &r, &r) & 255 ;

   getTitle()    /* - - - - - - -   G E T    T I T L E   - - - - - - - - */
      {
      int  length ;
         printf ("\t    Enter a song title  (not 3 char's.)  ",
                                                       titleLength );
         printf (" (or Enter  xxx  to quit) \n            |");
         for ( length = 1;  length  6 )
            printf ("     1 to 6 \b\b\b\b\b\b\b\b\b\b\b\b");
         }
      while  ( Minutes  6 );     /* end do...while */
      printf ("%1d:          \b\b\b\b\b\b\b\b\b\b", Minutes ) ;
      return  (Minutes);
      }

   /* ------------------------------------------------------------------ */
   getSeconds()  /* - - - - - -   G E T    S E C O N D S   - - - - - - - */
      {
      int Seconds;
      char string[4];
      do
         {
         gets  (string);
         Seconds = atoi (string);
         if (  Seconds  60 )
            printf ("\t     Seconds must be between  0 and 60 :  ");
         }
      while  ( Seconds  60 );
      return  (Seconds);
      }
   /* ------------------------------------------------------------------ */
   display_songs()  /* - - - - -   D I S P L A Y   S O N G S   - - - - - */
      {
      subttl_in_secs = 0 ;

      for ( this_one = 1;  this_one  %2d.  %2d. 


 

Turbo PASCAL

  {==================================}
   PROGRAM              MUSIC        ;
  {==================================}

  {--------------------- CONSTANTS ---------------------}
  const
        songs_limit = 40;    { number of songs that can be entered }
        title_length = 35;   { title string length limit;  char's. }
   type
        a_song_rec   =  record
           title     :  string[title_length];
           time      :  integer;
           minutes   :  integer;
           seconds   :  integer;
           cut_tim1  :  integer; { time without this song }
        end;
       all_the_songs = array[1..songs_limit] of a_song_rec;

  {---------------- VARIABLES ----------------}
   var
        atitle       : string[title_length];

        asong        : all_the_songs;
        ch           : char;
        songs        : integer;
        LastSong     : integer;
        this_song    : integer;
        xtraSongs    : integer;
        xtraSeconds  : integer;
        target_min   : integer;
        target_sec   : integer;
        subttlMin    : integer;
        subttlSec    : integer;
        subttlTim    : integer;
        xx, yy, zz   : integer;
        limit, diff  : integer;
        ttl_target_sec  : integer;
        out1, out2, out3, out4  : integer;

  {---------------------------- PROCEDURE -------------------------------}
  PROCEDURE   Read_a_Title ;
    begin
        atitle[0] := chr(title_length);
        for xx := 1 to title_length    do  aTitle[xx] := ' ' ;
        repeat
           Write   ('      ||   Enter A Blank Title To End');
           Write ('  ',LastSong+1:2,'  ');
           Readln ( aTitle );
           if  ( (atitle[0] =  chr(1))  or   (atitle[0] =  chr(2)) )  then
               Writeln ('A title must be more than 2 characters. ');
        until  ( (atitle[0]  chr(1))  and  (atitle[0]  chr(2)) )
    end;       { Read_a_Title }{
    }
  {-------------------------------------------------------------------}
  PROCEDURE  get_the_minutes   (ThisOne : integer)  ;
    begin
        repeat
            Write ('          1  to  6  Minutes: ');
            Readln (aSong[ThisOne].minutes);
        until      (aSong[ThisOne].minutes >= 1 ) and
                   (aSong[ThisOne].minutes = 0) and
                   (aSong[ThisOne].seconds  out1)  and  (this_one  out2)   and
                  (this_one  out3)  and  (this_one  out4) )   then
            begin
               Write (this_one:2, '.   ');
               Write (aSong[this_one].minutes:2 , ':');
               Write (aSong[this_one].seconds:2 , '   ');
               Write (aSong[this_one].title);
               Writeln;
               subttlTim :=  subttlTim + aSong[this_one].time ;
            end;
         end ;   {for}
        subttlSec := subttlTim mod 60;
        subttlMin := subttlTim div 60;
        Write ( subttlMin:8, ':', subttlSec:2, ' = total time ');
        Writeln;  Writeln;  Writeln; 
        Write ('  Off target by ', subttlTim - ttl_target_sec, ' sec''s.  ');
        Writeln  ('   target time = ', target_min:2, ':', target_sec:2);

        {  --------  now  print the cast-out(s)   --------  }
        Writeln ('                --- these were not used: ---  ');
        for  this_one  :=  1 to LastSong   do
        begin
            if  ( (this_one = out1)  or  (this_one = out2)   or
                  (this_one = out3)  or  (this_one = out4) )   then
            begin
               Write (this_one:12, '. ');
               Write (aSong[this_one].minutes:2 , ':');
               Write (aSong[this_one].seconds:2 , ' ');
               Write (aSong[this_one].title);
               Writeln;
            end;
        end ;   {for}
        Writeln (' ............................................... ');
        Writeln ('  --- hit  Enter  to continue ---  or ^C to quit ');
        Write   ('      or prt-scrn if you wish;  ... then {Enter} ');
        READln  (ch);  Writeln ;
    end;    { display_Songs }

  {-------------------------------------------------------------------}
  {                     M A I N    P R O G R A M                      }
  {-------------------------------------------------------------------}

begin
   for xx := 1 to songs_limit   do
        for  yy :=  1 to title_length  do
             asong[xx].title[yy] := ' ' ;
   Writeln ('          M A K I N G    A    C A S S E T T E    T A P E        ');
   Writeln ('          ----------------------------------------------        ');
   Writeln ('     Given that we enjoy recording our records onto tapes but   ');
   Writeln ('     we do NOT enjoy the tape coming to the end in the middle   ');
   Writeln ('     of a song,  this program enables a person to  . . .        ');
   Writeln ('     Enter a list of songs and their durations (min''s & sec''s)');
   Writeln ('     that total just over a required minimum,  ex: 30 minutes,  ');
   Writeln ('     plus 1 more song.   This program will then go through the  ');
   Writeln ('     list throwing out one song or another,  until it finds a   ');
   Writeln ('     total time that most nearly matches the target time.   It  ');
   Writeln ('     will then display the results.                             ');
   Writeln ('     ( p.s.   a 30 min. tape seems to last  31 min. & 30 sec.)  ');
   Writeln ('     (        a 45 min. tape seems to last  46 min. & 30 sec.)  ');
   Writeln ('     (        and  add  about  3 to 6  seconds between songs?)  ');
   Writeln;
   Writeln ('     Please  enter  the  total  target  time  for  one  side :  ');
   Writeln ('     (between 16 & 64 min.)                 ( otherwise quit )  ');
   Write   ('     ( 16 to 64 )  Minutes:  ');
   readln  (target_min);

   if  ( target_min >= 16 ) and ( target_min = 0)  and   (target_sec   7 ) or ( xtraSeconds = 0 ) ;

         { ------------------------------------------------------ }
         {                    enter the data                      }
         { ------------------------------------------------------ }
         subttlTim := 0 ;
         subttlMin := 0 ;
         subttlSec := 0 ;
         xtraSongs := 0 ;
         LastSong  := 0 ;
         Read_a_title;
         While ( aTitle[0]  chr(0) ) and ( xtraSongs   ' );
                 Write   ( target_min :2);
                 Writeln (':', target_sec :2);
                 if   ttl_target_sec  0  then              { ------------------------ }
             begin                            {      Make the Trades     }
                for xx := 1 to lastSong  do   { ------------------------ }
                   begin
                           {    cut_tim1 is the subtotal without that song  }
                      asong[xx].cut_tim1 := subttlTim - asong[xx].time;
                   end;
             limit := -1 ;
             repeat
                out1 := 0;  out2 := 0;
                out3 := 0;  out4 := 0;
                limit := limit + 1 ;
                for out1 := 1 to lastSong  do
                begin
                   {  see if throwing out 1 song  will work:  }
                   diff :=  ABS(asong[out1].cut_tim1 - ttl_target_sec);
                   if   (diff = limit)  then  display_songs;
                   {   see if throwing out 2 songs will work.  }
                   {           out1+1    you can't throw "out1" out twice }
                   for out2 := out1+1 to lastSong  do
                   begin
                      diff  :=  ABS(asong[out1].cut_tim1  -  asong[out2].time
                                                        -  ttl_target_sec) ;
                      if   (diff = limit)  then  display_songs;

                      { --- see if throwing out 3 songs will work: --- }
                      for out3 := out2+1 to lastSong  do
                      begin
                         diff :=  ABS(asong[out1].cut_tim1  -  asong[out2].time
                                   -  asong[out3].time      -  ttl_target_sec);
                         if  (diff = limit)  then  display_songs;
                         {  see if throwing out 4 songs will work:  }
                         for out4 := out3+1 to lastSong  do
                         begin
                            diff :=  ABS(asong[out1].cut_tim1  -  asong[out2].time
                                      -  asong[out3].time      -  asong[out4].time
                                                             -  ttl_target_sec);
                            if  (diff = limit)  then  display_songs;
                         end;  { for out4 }
                         out4 := 0 ;
                      end;  { for out3 }
                      out3 := 0 ;
                   end;  { for out2 }
                   out2 := 0 ;
                end;  { for out1 }
             until   limit > 40  ;
             Writeln ('              THIS PROGRAM STOPS at +/- 40  ');
             Writeln ('              seconds  of the  target time. ');
         end; { make the trades ...  IF  extra songs > 0 }
      end    { if target is between 16 & 64 }
   else
      begin
         Writeln (' Program terminated normally. ');
      end;
End.  { PROGRAM MUSIC }

Leave a Reply

We try to post all comments within 1 business day