home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Phoenix CD 2.0
/
Phoenix_CD.cdr
/
01e
/
libry31a.zip
/
LIBRY3.DOC
< prev
next >
Wrap
Text File
|
1987-01-20
|
16KB
|
372 lines
.pa
STRING AND BUFFER MANIPULATION
The purpose of these procedures is that FORTRAN is rather ill suited to
string and buffer manipulation. Most of the operations can be done in
FORTRAN but are extremely slow in comparison. Also there is the
annoying practice of some compilers (e.g. HP's FTN7X) to use fixed
length character variables. All of these routines were written in
assembler.
.pa
QUICK LIST OF STRING AND BUFFER MANIPULATION
CSET: set all the characters in a string
FOLD: case fold a character (a-z folds to A-Z)
FOLDS: case fold a character string (a-z folds to A-Z)
ISERCH: search for a character in a string
MATCH: check two character strings for a match
MOVEC: move one character string into another
MOVEI: move one integer array into another
NBUFC1: determine the nominal length of a character string
SWAPC: swap two character strings
SWAPI: swap two integer arrays
SORTC: sort a group of character strings
SORTCI: sort a group of indexed character strings
SORTD: sort an array of double precision reals
SORTDI: sort an array of indexed double precision reals
SORTI: sort an array of integers
SORTII: sort an array of indexed integers
SORTR: sort an array of reals
SORTRI: sort an array of indexed reals
DEC0DE: decode an array of reals contained in a character string
.pa
NAME: CSET
PURPOSE: set all the characters in a string equal to a specific
character (such as blanks)
TYPE: subroutine (far external)
SYNTAX: CALL CSET(CBUF,' ',NBUF)
INPUT: a CHARACTER*1 variable (here ' ')
NBUF (INTEGER*2) number of characters in the target string
OUTPUT: CBUF (CHARACTER*1 CBUF(NBUF) or CHARACTER*80 CBUF, NBUF=80)
NAME: FOLD
PURPOSE: case fold a character (a-z folds to A-Z)
TYPE: CHARACTER*1 function (far external)
SYNTAX: C2=FOLD(C1)
INPUT: C1 (CHARACTER*1)
OUTPUT: C2 (CHARACTER*1)
NAME: FOLDS
PURPOSE: case fold a character string (a-z folds to A-Z)
TYPE: subroutine (far external)
SYNTAX: CALL FOLDS(CBUF,NBUF)
INPUT: CBUF (CHARACTER*1 CBUF(NBUF) or CHARACTER*80 CBUF, NBUF=80)
NBUF (INTEGER*2) number of characters in the string
OUTPUT: CBUF
NAME: ISERCH
PURPOSE: search for a character in a string
TYPE: INTEGER*2 function (far external)
SYNTAX: K=ISERCH('?','are you kidding?',NBUF)
INPUT: a CHARACTER*1 variable (here '?')
CBUF (CHARACTER*1 CBUF(NBUF) or CHARACTER*80 CBUF, NBUF=80)
NBUF (INTEGER*2) number of characters in the string
OUTPUT: K (INTEGER*2)
NOTE: 0<=K<=NBUF (if found, I will be first occurrence, if not
found, K=0)
NAME: MATCH
PURPOSE: check two character strings for a match
TYPE: LOGICAL*2 function (far external)
SYNTAX: IF(MATCH(CBUF,'STOP',4)) GO TO 999
INPUT: two character strings (may be CHARACTER*1 CBUF1(NBUF),
CBUF2(NBUF) or CHARACTER*4 CBUF1,CBUF2)
NBUF (INTEGER*2) number of characters in the strings
OUTPUT: .true./.false.
NOTE: the strings need not have the same length as long as they are
both at least NBUF in length (here NBUF=4)
One annoying thing about FORTRAN is that it won't compare the
first 4 characters of a string read in as 4A1 with a string
of length 4 like 'STOP'. MATCH solves this problem.
NAME: MOVEC
PURPOSE: move one character string into another
TYPE: subroutine (far external)
SYNTAX: CALL MOVEC(CBUF1,CBUF2,NBUF) or CALL MOVEC(CBUF,'STOP',4)
INPUT: CBUF2 a character string (may be CHARACTER*1 CBUF2(NBUF) or
CHARACTER*4 CBUF2)
NBUF (INTEGER*2) number of characters in the strings
OUTPUT: CBUF1 a character string (may be CHARACTER*1 CBUF1(NBUF) or
CHARACTER*4 CBUF1)
NOTE: the strings need not have the same length as long as they are
both at least NBUF in length (here NBUF=4)
One annoying thing about FORTRAN is that it won't equivalence
first 4 characters of a 4A1 string to a string of length 4
like 'STOP'. MOVEC solves this problem. It's also much faster.
NAME: MOVEI
PURPOSE: move one integer array into another
TYPE: subroutine (far external)
SYNTAX: CALL MOVEI(IBUF1,IBUF2,NBUF)
INPUT: IBUF2 (INTEGER*2) an array
NBUF (INTEGER*2) number of elements in the arrays
OUTPUT: IBUF1 (INTEGER*2) an array
NOTE: the strings need not have the same length as long as they are
both at least NBUF in length
This is about seventeen times as fast as a FORTRAN "DO LOOP".
NAME: NBUFC1
PURPOSE: determine the nominal length of a character string excluding
trailing blanks
TYPE: INTEGER*2 function (far external)
SYNTAX: IF(NBUFC1(CBUF,80).EQ.0) STOP or
L=NBUFC1(CBUF,NBUF)
INPUT: CBUF a character string (may be CHARACTER*1 CBUF(NBUF) or
CHARACTER*4 CBUF)
NBUF (INTEGER*2) total number of characters in the string
OUTPUT: L (INTEGER*2) nominal length of string
NAME: SWAPC
PURPOSE: swap two character strings
TYPE: subroutine (far external)
SYNTAX: CALL SWAPC(CBUF1,CBUF2,NBUF)
INPUT: CBUF1 and CBUF2 character strings (may be CHARACTER*1
CBUF1(NBUF),CBUF2(NBUF) or CHARACTER*4 CBUF1,CBUF2)
NBUF (INTEGER*2) number of characters in the strings
OUTPUT: CBUF1,CBUF2
NOTE: the strings need not have the same length as long as they are
both at least NBUF in length
NAME: SWAPI
PURPOSE: swap two integer arrays
TYPE: subroutine (far external)
SYNTAX: CALL SWAPI(IBUF1,IBUF2,NBUF)
INPUT: IBUF1,IBUF2 (INTEGER*2) an arrays
NBUF (INTEGER*2) number of elements in the arrays
OUTPUT: IBUF1,IBUF2
NOTE: the arrays need not have the same length as long as they are
both at least NBUF in length
NAME: SORTC
PURPOSE: sort a group of character strings
TYPE: subroutine (far external)
SYNTAX: CALL SORTC(GROUP,L,N,ASCEND)
INPUT: GROUP a group of character strings (may be CHARACTER*1
GROUP(L,N) or CHARACTER*64 GROUP(N) if L=64)
L (INTEGER*2) length of the strings
N (INTEGER*2) number of strings in group
ASCEND (LOGICAL*2) .true. for ascending order, .false. for
descending order
OUTPUT: GROUP
NOTE: A modification of the shell sort is used.
This operation isn't even possible in FORTRAN because you
can't pass the length of a character variable as a formal
parameter.
WARNING: Be careful that GROUP does not cross a segment boundary!
That is, GROUP can not contain more than 65356 bytes nor
be part of a data group that spans a segment boundary. See
the comments in the section on vector emulation for more
details on segment boundaries.
NAME: SORTCI
PURPOSE: sort a group of indexed character strings
TYPE: subroutine (far external)
SYNTAX: CALL SORTCI(GROUP,L,INDEX,N,ASCEND)
INPUT: GROUP a group of character strings (may be CHARACTER*1
GROUP(L,N) or CHARACTER*64 GROUP(N) if L=64)
L (INTEGER*2) length of the strings
INDEX (INTEGER*2) some index like 1,2,3,4,5...
N (INTEGER*2) number of strings in group
ASCEND (LOGICAL*2) .true. for ascending order, .false. for
descending order
OUTPUT: GROUP, INDEX (if, for example, you set INDEX to 1,2,3,4,5...
upon return from SORTCI you can tell what the change was from
the original order - INDEX will come back as something like
13,2,35,27,3,18,...)
NOTE: A modification of the shell sort is used.
This operation isn't even possible in FORTRAN because you
can't pass the length of a character variable as a formal
parameter.
WARNING: Be careful that GROUP and INDEX do not cross segment
boundaries. That is, GROUP can not contain more than 65356
bytes and INDEX can not contain mode than 32768 elements nor
be part of a data group that spans a segment boundary. See
the comments in the section on vector emulation for more
details on segment boundaries.
NAME: SORTD
PURPOSE: sort an array of double precision reals
TYPE: subroutine (far external)
SYNTAX: CALL SORTD(D,N,ASCEND)
INPUT: D (REAL*8) array
N (INTEGER*2) number of elements in D
ASCEND (LOGICAL*2) .true. for ascending order, .false. for
descending order
OUTPUT: D
NOTE: A modification of the shell sort is used.
WARNING: Be careful that D does not cross a segment boundary!
That is, D can not contain more than 8192 elements nor
be part of a data group that spans a segment boundary. See
the comments in the section on vector emulation for more
details on segment boundaries.
NAME: SORTDI
PURPOSE: sort an array of indexed double precision reals
TYPE: subroutine (far external)
SYNTAX: CALL SORTDI(D,INDEX,N,ASCEND)
INPUT: D (REAL*8) array
INDEX (INTEGER*2) some index like 1,2,3,4,5...
N (INTEGER*2) number of elements in D
ASCEND (LOGICAL*2) .true. for ascending order, .false. for
descending order
OUTPUT: D, INDEX (if, for example, you set INDEX to 1,2,3,4,5...
upon return from SORTDI you can tell what the change was from
the original order - INDEX will come back as something like
13,2,35,27,3,18,...)
NOTE: A modification of the shell sort is used.
WARNING: Be careful that D and INDEX do not cross segment
boundaries. That is, D can not contain more than 8192
bytes and INDEX can not contain mode than 32766 elements nor
be part of a data group that spans a segment boundary. See
the comments in the section on vector emulation for more
details on segment boundaries.
NAME: SORTI
PURPOSE: sort an array of integers
TYPE: subroutine (far external)
SYNTAX: CALL SORTI(K,N,ASCEND)
INPUT: K (INTEGER*2) array
N (INTEGER*2) number of elements in K
ASCEND (LOGICAL*2) .true. for ascending order, .false. for
descending order
OUTPUT: K
NOTE: A modification of the shell sort is used.
WARNING: Be careful that K does not cross a segment boundary!
That is, K can not contain more than 32768 elements nor
be part of a data group that spans a segment boundary. See
the comments in the section on vector emulation for more
details on segment boundaries.
NAME: SORTII
PURPOSE: sort an array of indexed integers
TYPE: subroutine (far external)
SYNTAX: CALL SORTII(K,INDEX,N,ASCEND)
INPUT: K (INTEGER*2) array
INDEX (INTEGER*2) some index like 1,2,3,4,5...
N (INTEGER*2) number of elements in K
ASCEND (LOGICAL*2) .true. for ascending order, .false. for
descending order
OUTPUT: K, INDEX (if, for example, you set INDEX to 1,2,3,4,5...
upon return from SORTII you can tell what the change was from
the original order - INDEX will come back as something like
13,2,35,27,3,18,...)
NOTE: A modification of the shell sort is used.
WARNING: Be careful that K and INDEX do not cross segment
boundaries. That is, K can not contain more than 32768
bytes and INDEX can not contain mode than 32766 elements nor
be part of a data group that spans a segment boundary. See
the comments in the section on vector emulation for more
details on segment boundaries.
NAME: SORTR
PURPOSE: sort an array of reals
TYPE: subroutine (far external)
SYNTAX: CALL SORTR(R,N,ASCEND)
INPUT: R (REAL*4) array
N (INTEGER*2) number of elements in R
ASCEND (LOGICAL*2) .true. for ascending order, .false. for
descending order
OUTPUT: R
NOTE: A modification of the shell sort is used.
WARNING: Be careful that R does not cross a segment boundary!
That is, R can not contain more than 16384 elements nor
be part of a data group that spans a segment boundary. See
the comments in the section on vector emulation for more
details on segment boundaries.
NAME: SORTRI
PURPOSE: sort an array of indexed reals
TYPE: subroutine (far external)
SYNTAX: CALL SORTRI(R,INDEX,N,ASCEND)
INPUT: R (REAL*4) array
INDEX (INTEGER*2) some index like 1,2,3,4,5...
N (INTEGER*2) number of elements in R
ASCEND (LOGICAL*2) .true. for ascending order, .false. for
descending order
OUTPUT: R, INDEX (if, for example, you set INDEX to 1,2,3,4,5...
upon return from SORTRI you can tell what the change was from
the original order - INDEX will come back as something like
13,2,35,27,3,18,...)
NOTE: A modification of the shell sort is used.
WARNING: Be careful that R and INDEX do not cross segment
boundaries. That is, R can not contain more than 16384
bytes and INDEX can not contain mode than 32766 elements nor
be part of a data group that spans a segment boundary. See
the comments in the section on vector emulation for more
details on segment boundaries.
NAME: DEC0DE (note the "0" (zero), do not use an "O" (oh))
PURPOSE: decode an array of reals contained in a character string
TYPE: subroutine (far external)
SYNTAX: CALL DEC0DE(CBUF,NBUF,NCOL,R,N,IER)
INPUT: CBUF (any character string like '123 34.E4 5*0 100')
NBUF (INTEGER*2) the number of characters in CBUF
N (INTEGER*2) number of elements in R
OUTPUT: NCOL (INTEGER*2) the column where decoding stopped
R (REAL*4) an array (may be only 1 element)
IER (INTEGER*2) error return indicator (IER=0 is normal)
NOTE: In case you haven't noticed, some misguided persons at DEC and
Microsoft forgot to include the capability of free-format
reads from a character string (some people call character
strings "internal files" - why, is a mystery to me). Of
course, this is the most OBVIOUS reason for reading something
from a character string... perhaps that's why they left it
out. Well, DEC0DE is just the fix.
DEC0DE will return an error if the syntax is incorrect or if
the string is empty. You must have at least one number in the
string. Missing numbers at the trailing end of a string will
be set to zero (viz. if you try to read 6 numbers and there
are only 3, the last 3 will come back as zero).
Some examples of free format reals are given below. Note that
you can use the "*" to repeat numbers. Commas are optional.
100 1.234 .0000123,45E4, 3*53.123 5*-7 -12.345E-05
DEC0DE is written in assembler and is actually faster than
Microsoft's or HP's equivalent. HP's FORTRAN will actually
perform this operation.
When I want to read integers from a character string I first
read reals, then apply the "NINT" function as below
CALL DEC0DE(CBUF,6,NCOL,R,1,IER)
IF(IER.NE.0) GO TO 999
I=NINT(R)
The NINT function performs the real>integer conversion that is
what you probably want: (nearest integer) rather than the INT
function (truncate to integer).