      PROGRAM CHEM
************************************************************************
* Program to read a file containing the chemical formula, name, and    *
* specific heat for various inorganic compounds and store these in     *
* parallel arrays.  File is sorted so that the formulas are in         *
* alphabetical order.  The user enters a formula; the list of formulas *
* is searched using the binary search algorithm; and if the formula is *
* found, its name and specific heat are displayed.   Identifiers used  *
* are:                                                                 *
*     LIMIT   :  parameter specifying maximum # of array elements      *
*     LENGTH  :  parameter specifying length of character strings      *
*     FORMUL  :  array of formulas                                     *
*     NAME    :  array of names                                        *
*     SPHEAT  :  array of specific heats                               *
*     N       :  number of records in the file                         *
*                                                                      *
* Input:  Arrays FORMUL, NAME, and SPHEAT (from RDDATA)                *
* Output: Names and specific heats for certain formulas (by LOOKUP)    *
************************************************************************

      INTEGER LIMIT, LENGTH, N
      PARAMETER (LIMIT = 100, LENGTH = 10)
      CHARACTER*(LENGTH) FORMUL(LIMIT), NAME(LIMIT)*(2*LENGTH)
      REAL SPHEAT(LIMIT)

      CALL RDDATA(FORMUL, NAME, SPHEAT, LIMIT, N)
      CALL LOOKUP(FORMUL, NAME, SPHEAT, LIMIT, N)
    
      END


**RDDATA****************************************************************
* Subroutine to read a list of up to LIM chemical formulas, names,     *
* and specific heats, store them in parallel arrays FORMUL, NAME, and  *
* SPHEAT, and count (N) how many sets of readings are stored.  FNAME   *
* is the name of the file from which data is read and EOF is an        *
* end-of-file indicator.                                               *
*                                                                      *
* Accepts:          Arrays FORMUL, NAME, SPHEAT, N (undefined) and     *
*                   integer LIM                                        *
* Input (keyboard): File name FNAME                                    *
* Input (file):     Elements of FORMUL, NAME, SPHEAT                   *
* Returns:          Arrays FORMUL, NAME, SPHEAT(modified) and integer N*
************************************************************************

      SUBROUTINE RDDATA(FORMUL, NAME, SPHEAT, LIM, N)
      INTEGER LIM, N, EOF
      CHARACTER*(*) FORMUL(LIM), NAME(LIM)
      REAL SPHEAT(LIM)
      CHARACTER*20 FNAME
    
* Open the file, then read, count, and store the items

      PRINT *, 'ENTER NAME OF FILE'
      READ '(A)', FNAME
      OPEN (UNIT = 15, FILE = FNAME, STATUS = 'OLD')
      N = 1

*     While there is more data in the file, read it and
*     store it in the parallel arrays

      READ (UNIT = 15, FMT = 100, IOSTAT = EOF)
     +      FORMUL(N), NAME(N), SPHEAT(N)
 100  FORMAT(2A, F5.0)
 10   IF (EOF .GE. 0) THEN
         N = N + 1
         READ (UNIT = 15, FMT = 100, IOSTAT = EOF)
     +        FORMUL(N), NAME(N), SPHEAT(N)
         GO TO 10
      ELSE
         N = N - 1
      END IF

      CLOSE(15)

      END


**LOOKUP****************************************************************
* Subroutine that allows user to enter formulas.  The array FORMUL     *
* having N chemical formulas is then searched for this formula, and    *
* if found, the corresponding elements of the parallel arrays NAME     *
* and SPHEAT are displayed.  User enters QUIT to stop searching. LIM   *
* dimensions the arrays, and LENGTH is used to specify the lengths of  *
* the formulas and names.  Local identifiers used are:                 *
*     UFORM   :  formula entered by the user                           *
*     FOUND   :  signals if UFORM found in array FORMUL                *
*     LOC     :  location of UFORM in FORMUL if found                  *
*     LENGTH  :  parameter used to specify length of UFORM             *
*                                                                      *
* Accepts:          Arrays FORMUL, NAME, SPHEAT, and                   *
*                   integers LIM and N                                 *
* Input (keyboard): Several values of UFORM or a 'QUIT' signal         *
* Output:           For each formula that is found, its specific       *
*                   heat; otherwise a 'NOT FOUND' message              *
************************************************************************

      SUBROUTINE LOOKUP(FORMUL, NAME, SPHEAT, LIM, N)

      INTEGER LIM, N, LOC, LENGTH
      PARAMETER (LENGTH = 10)
      CHARACTER*(*) FORMUL(LIM), NAME(LIM)
      CHARACTER*(LENGTH) UFORM
      REAL SPHEAT(LIM)
      LOGICAL FOUND

      PRINT *
      PRINT *, 'ENTER FORMULA TO SEARCH FOR, (QUIT TO STOP)'
      READ '(A)', UFORM

* While UFORM not equal to 'QUIT',  search FORMUL array for it, 
* display information found, and read next UFORM

 10   IF (UFORM.NE. 'QUIT') THEN
         CALL LINSCH(FORMUL, LIMIT, N, UFORM, FOUND, LOC)
         IF (FOUND) THEN
            PRINT 100, 'HAS SPECIFIC HEAT', SPHEAT(LOC)
 100        FORMAT(6X, A, F7.4)
         ELSE
            PRINT 100, ' NOT FOUND'
         END IF
         PRINT *
         PRINT *, 'ENTER FORMULA TO SEARCH FOR, (QUIT TO STOP)'
         READ '(A)', UFORM
      GO TO 10
      END IF

      END

**LINSCH****************************************************************
* Subroutine to search the list ITEM For UITEM using linear search.    *
* If UITEM is found in the list, FOUND is returned as true and the     *
* LOCation of the item is returned; otherwise FOUND is false.  LIM is  *
* the limit on the size of ITEM.                                       *
*                                                                      *
* Accepts:  Array ITEM, integers LIM and N, and UITEM                  *
* Returns:  If UITEM is found:                                         *
*              FOUND = true and LOC = its position in the list ITEM    *
*           Otherwise:                                                 *
*              FOUND = false (and LOC = last position examined)        *
************************************************************************

      SUBROUTINE LINSCH(ITEM, LIM, N, UITEM, FOUND, LOC)

      INTEGER LIM, N, LOC
      CHARACTER*(*) ITEM(LIM), UITEM
      LOGICAL FOUND

      LOC = 1
      FOUND = .FALSE.

*     While LOC less than or equal to N and not FOUND do

 10   IF ((LOC .LE. N) .AND. .NOT. FOUND) THEN
         IF (UITEM .EQ. ITEM(LOC)) THEN
            FOUND = .TRUE.
         ELSE
            LOC = LOC + 1
         END IF
      GO TO 10
      END IF

      END
