{********************************************************} {* *} {* PROGRAM TITLE: STRING Functions Demonstration *} {* *} {* WRITTEN BY: Raymond E. Penley *} {* DATE WRITTEN: 27 MAY 80 *} {* *} {* WRITTEN FOR: Pascal/Z Users Group *} {* *} {* NOTE: *} {* All comments about the string library are *} {* found in the file 'STRLIB.DOC' *} {* *} {********************************************************} PROGRAM StringDemo; CONST master = 'THE QUICK BROWN FOX JUMPED OVER THE LAZY BLACK DOG'; sign5 = 'This is the master string we will be using:'; space = ' '; StrMax = 255; {maximum length of a string} (* !!!! IMPLEMENTATION DEPENDENT !!!! *) INPUT = 0; TYPE alfa = STRING 10 ;{just the right size} string40 = STRING 40 ;{ 1/2 of default length } string79 = STRING 79 ;{ ONE less than default length } string80 = STRING 80 ;{ DEFAULT length for strings } MString = STRING StrMax ;{ The BIG GUN } (*---Use these for the Pascal/Z supplied functins---*) $STRING0 = STRING 0 ; $STRING255 = STRING Strmax ; VAR error : Boolean; {---required for the STRING Library---} (*---Required for Pascal/Z supplied string functins---*) FUNCTION LENGTH(X: $STRING255): INTEGER; EXTERNAL; FUNCTION INDEX(X,Y :$STRING255): INTEGER; EXTERNAL; PROCEDURE SETLENGTH(VAR X :$STRING0; Y :INTEGER); EXTERNAL; (*----------------------------------------------------*) (************************************************) Function UCase(ch : char) : char; (*---Returns an uppercase ASCII character---*) begin If ch IN ['a'..'z'] then UCase := CHR(ORD(ch) -32) Else UCase := ch end; (************************************************) {---------------------------------------} { STRLIB LIBRARY } {---------------------------------------} PROCEDURE PRINT( A : MString); VAR I : 1..StrMax; begin If (LENGTH(A) > 0) and (LENGTH(A) <= StrMax) then For I:= 1 to LENGTH(A) do write(A[ I ]) Else Write(space) end; (*********************************************) PROCEDURE COPY( { TO } VAR dest : string80 ; { FROM } THIS : MSTRING ; {STARTING AT} POSN : INTEGER ; {# OF CHARS } LEN : INTEGER ) ; { COPY(NEW_NAME, NBUF, NAME_ADDR, NAME_LEN); } { COPY(A_STRING, A_STRING, 5, 5); } {GLOBAL StrMax = 255; MSTRING = STRING StrMax; } LABEL 99; CONST line_length = 80 ; VAR ix : 1..StrMax; begin SETLENGTH(dest,0); {length returned string=0} If (len + posn) > line_length then{exit}goto 99; IF ((len+posn-1) <= LENGTH(this)) and (len > 0) and (posn > 0) then FOR ix:=1 to len do APPEND(dest, this[posn+ix-1]); 99: {Any error returns dest with a length of ZERO.} End{of COPY}; (*********************************************) PROCEDURE CONCAT({New_String} VAR C : string80 ; {Arg1_str } A : Mstring ; {Arg2_str } B : Mstring ); { CONCAT(New_string, Arg1, Arg2); } CONST line_length = 80; VAR ix : 1..StrMax; begin SETLENGTH(C,0); If (LENGTH(A) + LENGTH(B)) <= line_length then begin APPEND(C,A); APPEND(C,B); end; {If error then returns length of new_string=0} End{of CONCAT}; (*********************************************) PROCEDURE REPLACE(VAR source : string80; VAR dest : string80; K1 : Integer); (* * REPLACE(Source, Destination, Index); * REPLACE(Sub,Next,N); *) CONST line_length = 80; VAR temp1,temp2 : Mstring; pos, k : 1..StrMax; begin If (K1 > 0) and (K1 <= LENGTH(dest)) and (K1 <= line_length) then begin (* Position 'K1' is within STRING 'dest' *) (* but not longer than line_length *) SETLENGTH(temp1,0); SETLENGTH(temp2,0); COPY(temp1,dest,1,K1-1); APPEND(temp1,source);(* concatenate temp1 and A *) k := K1 + LENGTH(source);(* extract remaining chars from dest *) COPY(temp2,dest,k,(LENGTH(dest)-k+1)); CONCAT(dest,temp1,temp2) end(*If*) Else(* Issue error message and do nothing *) Writeln('Index out of range') end(* of REPLACE *); (*********************************************) Procedure GetLine( VAR Agr_string : string80 ; count : integer ); (*----------------------------------------------*) (* version: 31 MAY 80 by R.E.Penley *) (* Valid Alphanumeric chars are: *) (* from the ASCII space - CHR(32) to the *) (* ASCII tilde - CHR(126) *) (* In order to get this to work with *) (* Pascal/Z v 3.0 I have defined a line *) (* as a string[80] *) (*----------------------------------------------*) (* GLOBAL StrMax = 255; Mstring = STRING 255; error : boolean; <> *) CONST SPACE = ' '; a_error = 'Alphanumerics only - '; line_length = 80; VAR InChar : char; CHAR_COUNT : INTEGER; ix : 1..StrMax; begin error := false; SETLENGTH( Agr_string, 0 ); CHAR_COUNT := 0; REPEAT If (count <= line_length) AND (CHAR_COUNT < count) then begin{start accepting chars} READ( InChar ); If InChar IN [' ' .. '~'] then{valid char} begin{increment CHAR_COUNT and store InChar} CHAR_COUNT := char_count + 1 ; APPEND( Agr_string, InChar ); end(* If *) Else (* we have a non-acceptable character *) begin WRITELN(a_error); error:=TRUE end(* else *) end(* If *) Else (* ERROR *) begin (* RESET EndOfLine *) {} READLN( Agr_string[ CHAR_COUNT ] ); WRITELN('Maximum of', count:4, ' characters please!'); error:=TRUE end(* else *) UNTIL EOLN(INPUT) or error; If error then{return a length of zero} SETLENGTH( Agr_string, 0 ); End{of GetLine}; {---------------------------------------} { UTILITY ROUTINES } {---------------------------------------} Procedure DRAW(picture : Mstring ; count : integer); VAR ix : integer; begin For ix:=1 to count do WRITE(picture); end; Procedure DELAY(timer:integer); { DELAY(10); will give about 1 second delay } { DELAY(5); will give about 0.5 second delay } { DELAY(30); will give about 3 second delay } CONST factor = 172; var ix,jx : integer; begin for ix:=1 to factor do for jx:=1 to timer do {dummy}; end; Function QUIRY(message : string80) : boolean ; { Try to write a general purpose } { routine that gets a 'YES' or 'NO' } { response from the user. } VAR ans : string 2; valid : boolean; begin Repeat valid := false; Write(message); readln(ans); If ans='OK' then begin valid := true; QUIRY := true end Else If ans[1] IN ['Y','y','N','n'] then begin valid := true; QUIRY := ( (ans='Y') or (ans='y') ) end Until valid{response} end{of Quiry}; Procedure CLEAR; var ix :1..25; begin for ix:=1 to 25 do writeln end; Procedure SKIP(n : integer); var ix : 0..255; begin for ix:=1 to n do writeln end; Procedure PAUSE; CONST sign = 'Enter return to continue '; var ch : char; begin write(sign); readln(CH) end; Procedure HEADER( title : string80 ); CONST left_margin = 11; right_margin = 51; center = 31; dashes = '{---------------------------------------}'; VAR F1, {filler left side} F2, {filler right side} CL, {center line of title} len {length of title} : integer; begin len := LENGTH(title); CL := len DIV 2; {If length of title is odd then increase CL by one} If ODD(len) then CL := CL +1; F1 := (center - CL) - left_margin; {If length of title is even then reduce F1 by 1 } If not ODD(len) then F1 := F1 - 1; F2 := right_margin - (center + CL); writeln(' ':left_margin,dashes); writeln(' ':left_margin,'{',' ':F1,title,' ':F2,'}'); writeln(' ':left_margin,dashes); end; {---------------------------------------} { DEMONSTRATION ROUTINES } {---------------------------------------} Procedure Simple_IO; VAR line : string80; C : char; again: boolean; begin CLEAR; writeln;writeln; HEADER('Input/Output DEMONSTRATION'); SKIP(5); REPEAT WRITE('Enter one character >'); Readln(C); WRITELN('The Char you entered was ', C); writeln;writeln; again := QUIRY('Again? '); Until not again; Repeat Repeat WRITELN; WRITELN('Input a short string'); WRITELN(' <--- Max 10 char'); WRITE('>>'); GetLine(line,10); IF NOT error THEN begin WRITELN; WRITE('You entered a'); write(LENGTH(line):3, ' Character String. >'); PRINT(line);Writeln; end; Until not error; writeln;writeln; again := QUIRY('Again? '); Until not again; End{of I/O demo}; Procedure Str_Comp; VAR S : string 40; T : string 20; begin S := 'SOMETHING'; T := 'SOMETHING BIGGER'; CLEAR; HEADER('STRING COMPARISONS'); SKIP(2); writeln('First we will compare these two string variables:'); writeln('1. ',S); writeln('2. ',T); DELAY(20); IF S=T THEN WRITELN('Strings do not work very well') ELSE IF S > T THEN WRITELN(S, ' is greater than ', T) ELSE IF S < T THEN WRITELN(S, ' is less than ', T); writeln; writeln('Now to compare the variable string S against the'); writeln('literal strings ''SOMETHING'' and ''SAMETHING'''); DELAY(20); IF S = 'SOMETHING' THEN WRITELN(S, ' equals ', S); IF S > 'SAMETHING' THEN WRITELN(S, ' is greater than SAMETHING'); writeln; PAUSE; writeln; writeln('The same test but with extra blanks in the literal string'); DELAY(10); IF S = 'SOMETHING ' THEN WRITELN('BLANKS DON''T COUNT') ELSE WRITELN('BLANKS APPEAR TO MAKE A DIFFERENCE'); writeln; writeln('Now to change the variable strings:'); writeln('1. S := ''XXX'''); writeln('2. T := ''ABCDEF'''); S := 'XXX' ; T := 'ABCDEF' ; DELAY(20); IF S > T THEN WRITELN(S, ' is greater than ', T) ELSE WRITELN(S, ' is less than ',T); writeln;writeln; PAUSE; End{of Str_Comp}; Procedure Copy_demo; (* global master : string80; *) CONST sign1 = 'First - Enter the starting position in the main string'; sign2 = 'Next - Enter the number of chars to copy'; VAR sub : string 80; again : boolean; start, count : INTEGER; begin CLEAR; HEADER('STRING COPY'); writeln;writeln; WRITELN(sign5); Repeat WRITELN; WRITELN(master); writeln;writeln; Writeln(sign1); WRITE(' >'); Readln(start); Writeln(sign2); write(' >'); Readln(count); WRITELN; COPY(SUB,master,start,count); write('The substring = ');WRITELN(SUB); writeln;writeln; again := QUIRY('Again? '); Until not again; End{of Copy_demo}; Procedure C_cat_demo; VAR strg1,strg2, sub : string 80; again : boolean; begin CLEAR; HEADER('CONCATENATION DEMONSTRATION'); writeln;writeln; Repeat writeln;writeln; writeln('Now to CONCAT two strings'); writeln('Enter a short string'); GetLine(strg1,40); writeln('Enter another short string'); GetLine(strg2,40); CONCAT(sub,strg1,strg2); writeln(SUB); writeln;writeln; again := QUIRY('Again? '); Until not again; end{of C_cat_demo}; Procedure Replc_demo; CONST sign1 = 'First - give me a short string within the master'; VAR pattern, work : string80; pos : integer; again : boolean; begin CLEAR; HEADER('Position & Replace demo'); writeln;writeln; WRITELN(sign5); Repeat work := master; WRITELN; WRITELN(work); writeln;writeln; Writeln(sign1); WRITE(' >'); Readln(pattern); pos := INDEX(work,pattern); writeln('The position of ',pattern,' is : ',pos); writeln; writeln('Now to replace `BROWN` with `APPLE`'); writeln; pattern := 'APPLE'; pos := INDEX(work,'BROWN'); REPLACE(pattern,work,pos); writeln(work); writeln; writeln('Finally to replace `LAZY BLACK DOG`'); writeln; pattern := 'SLOW TURTLE'; pos := INDEX(work,'LAZY'); REPLACE(pattern,work,pos); writeln(work); writeln;writeln; again := QUIRY('Again? '); Until not again; End{of Replc_demo}; Procedure SIGNON; var ix : integer; begin For ix := 1 to 2 do begin DRAW('*',72);writeln end; DRAW('*',4);DRAW(' ',64);DRAW('*',4);writeln; DRAW('*',4); WRITE(' ':22, 'STRING DEMONSTRATION',' ':22); DRAW('*',4);writeln; DRAW('*',4);DRAW(' ',64);DRAW('*',4);writeln; For ix := 1 to 2 do begin DRAW('*',72);writeln end; end{of signon}; Procedure Wrap_up; begin CLEAR; HEADER('=*= Pascal/Z is good! =*='); writeln;writeln; writeln('That concludes the demonstration'); writeln('You are invited to look over this Pascal program.'); writeln('There are many procedures and functions that should'); writeln('be included in your library.'); writeln('If you have any questions or can make any improvements'); writeln('please send them to the:'); writeln; writeln(' ':12,'===/'); writeln(' ':12,' / USERS GROUP'); writeln(' ':12,' /========================'); writeln(' ':12,'7962 Center Parkway'); writeln(' ':12,'Sacramento, CA. 95823'); SKIP(5); end{of wrap_up}; {---------------------------------------} { MASTER CONTROL PROGRAM } {---------------------------------------} Begin{main program} CLEAR; SIGNON; SKIP(10); DELAY(40);{4 seconds delay}; Simple_IO; Str_Comp; Copy_demo; C_cat_demo; Replc_demo; Wrap_up; End{of Demonstration}. .