Strings are arrays of characters of a specified maximum length.
Strings are structured types; that is, they can be broken down
into their individual components. Strings in Turbo Pascal V7
have a default length of 255 and are declared by the keyword
String; otherwise, their maximum length must be declared when
they are defined. Strings may grow dynamically from length 0 (=
"empty string" or "null string") to an absolute maximum of length
255. Examples:
Type
File_name = String[14]; { max length = 14 }
Employee_name = String[30];
Var
Infile_name: File_name;
Emp_name: Employee_name;
Line: String; { max length = 255 }
The READ and WRITE procedures support strings, so that (using the
above definitions), Read(Emp_name) and Writeln(Infile_name) are
legal Pascal statements. There are many methods for modifying and comparing strings:
:=
Strings may be assigned values using the := operator.
Example: Infile_name := 'A:\PROG006.OUT'; Note that if we
attempted to make the following assignment:
Infile_name :='A:\OUTPUT\PROG006.OUT', the value assigned to Infile_name
would be 'A:\OUTPUT\PROG' which may not be what we expected!
Also, Infile_name[2] = ':' and Infile_name[11] = 'P'.
+
Example: Infile_name := 'A:\' + 'PROG006' + '.OUT';
St[n]
Example: Writeln(Infile_name[3]);
causes the third character of Infile_name to be printed.
=, <, <=, >, >=, <>If X and Y are strings, then X r Y is either TRUE or FALSE where r is any of the six relational characters listed above. X = Y is true if and only if their lengths are equal and X[i] = Y[i] for all i = 1, 2, .... When X and Y are compared, X[i] and Y[i] are compared in sequence according to their ASCII ordinal values. If the strings are of different length but equal character by character up to and including the last character of the shorter string, then the shorter string is considered smaller. Examples:
'A' < 'B' TRUE
'Z' < 'a' TRUE
'a' < 'B' FALSE
'TURBO' ='TURBO' TRUE
'TURBO' = 'Turbo' FALSE
'turbo ' = 'turbo' FALSE
'turbo ' > 'turbo' TRUE
Length(St)Returns the current length of the string St in range 0..255.
Example:
Var
St: String[20]; Len: Integer;
St := ''; { make St the null string }
Len := Length(St); { Len now has value 0 }
St := St + 'Begin';
Len := Length(St); { Len now has value 5 }
Pos(Pattern, Target)
The Pos function scans the string Target to find the first
occurrence of the string Pattern in the string Target. The
value returned by Pos is an integer indicating this
position. When the string Pattern is not found in Target,
Pos returns the value zero.
Example:
Var Target, Pattern: String[20];
Location: Integer;
Target := 'MISSISSIPPI';
Pattern := 'IS';
Location := Pos(Pattern, Target); { Location = 2 }
If Pattern = 'SIP', then Location = 7.Pattern = 'is', then Location = 0.Pattern = ' ', then Location = 0.
Copy(St, Start, Number)
The Copy function returns a substring copied out of St
starting at position Start containing Number characters.
Thus St is a string expression and Start and
Number are
positive integers. If Start > Length(St), the empty string
is returned. If Start + Number > Length(St), only
characters in the string St are returned. If Start is
outside the range 1..255, a run-time error occurs.
Example:
Var St, Part: String[20];
Start, Number: Integer;
St := 'MISSISSIPPI';
Start := 5;
Number := 3;
Part := Copy(St, Start, Number); { Part = 'ISS' }
If Start = 12, then Part = ''.Start = 5 and Number = 20, then Part = 'ISSIPPI'.
Delete(St, Start, Number)
This procedure will alter St by removing Number characters
from St beginning at position Start. If Start > Length(St),
no characters will be removed from St. If Start + Number >
Length(St), only characters in the string will be removed.
Example (using above defined storage):
St := 'MISSISSIPPI';
Start := 5;
Number := 4;
Delete(St, Start, Number); { St = 'MISSPPI' }
If Start = 15, St does not change.Start = 2 and Number = 20, then Delete(St, Start, Number) changes St to 'M'.
Insert(Pattern, Target, Position)
Insert actually places a copy of the string Pattern into the
string Target to the left of the character at location
Position. Thus Target will be altered by Insert. If
Position > Length(Target), Pattern will be concatenated to
the end of Target to the extent possible.
Example (using above defined storage):
Target := 'MISSISSIPPI';
Part := 'xyz';
Insert(Part, Target, 5); { Target = 'MISSxyzISSIPPI' }
If Part = 'abcdefghijkl' and Position = 7, then Insert(Part, Target, Position) Target to 'MISSISabcdefghijklSI'. Position = 70, then Target = 'MISSISSIPPIabcdefghi'.
VAL(St, Num, Error_code)
Purpose: to convert a string value which is in the form of a
valid numeric quantity to the numeric value it represents.
If the conversion can be made without error, the value is
placed in Num (and the conversion is controlled by the
declared numeric type of Num) and Error_code = 0. If an
error occurs, the value of Num is unchanged; Error_code > 0
and points to the first position in St where a conversion
error occurred. Examples:
Var
Num_str: String[20];
R_Num: Real;
I_num, Error: Integer;
Num_str := '23.45';
Val(Num_str, R_Num, Error); {R_Num = 23.45, Error = 0}
Val(Num_str, I_Num, Error); {Error = 3; R_Num stays 23.45 }
Num_str := '256,78';
Val(Num_str, R_Num, Error); {R_Num = 23.45, Error = 4}
Num_str := '23456';
Val(Num_str, I_Num, Error); {I_Num = 23456, Error = 0}
Val(Num_str, R_Num, Error); {R_Num = 23456.0, Error = 0}
STR(Numeric, St)
Purpose: to perform the inverse function of VAL; that is, to
receive a numeric value and convert it (according to any
formatting information) to a string.
Examples (using the storage defined in 10);
Result is String[20]:
I_Num := -345;
Str(I_num, Result); {Result = '-345'}
R_num := 2345.678;
Str(R_num :0:6, Result); {Result = '2345.678000'}
Str(R_num :0:1, Result); {Result = '2345.7'}
Str(R_num :10:2, Result); {Result = ' 2345.68'}
Str(R_num, Result); {Result = ' 2.3456780000E+03'}
Const Space = ' '; Var St, First, Last: String[80]; Position, Len: Integer; Remove: Char;
St := ' now is the time'; While POS(Space, St) = 1 Do Delete(St, 1, 1);
St := 'Smith John';
Location := POS(Space, St); { Location = 6 }
Len := Length(St); { Len = 10 }
Last := COPY(St, 1, Location - 1); { Last = 'SMITH'}
First := COPY(St, Location + 1, Len - Location);
St := First + Space + Last;
St := 'Txxhixs xsenxtxxencxe hxxaxs toxxox xmaxxny exxexes.';
Remove := 'x';
New := '';
For Location := 1 to Length(St) Do
If St[Location] <> Remove
Then New := New + St[Location];
What's wrong with using a loop like this:
For Location := 1 to Length(St) Do
If St[Location] = Remove
Then Delete(St, Location, 1);
Answer: will only remove isolated single 'x's in string
Const
Blank = ' ';
Var
St, New: String[80];
Location, Mid: 1..80;
New := ''; {New is the null string }
For Location := 1 to Length(St) Do
If Location MOD 5 = 0
Then New := New + St[Location] + Blank
Else New := New + St[Location];
New := ''; For Location := Length(St) downto 1 Do New := New + St[Location];
Var
St, New: String[80];
Location, Mid: 1..80;
Count: 0..80;
Valid_Ch: Set of Char;
Count := 0;
Valid_Ch := ['A', 'E', 'I', 'O', 'U', 'a', 'e', 'i', 'o', 'u'];
For Location := 1 to Length(St) Do
If St[Location] IN Valid_Ch
Then Count := SUCC(Count);
Writeln('There were ', Count, ' vowels in ', St);
{ convert lower case letters to upper case }
For Location := 1 to Length(St) Do
St[Location] := UPCASE(St[Location]);
{ convert upper case letters to lower case }
Valid_Ch := ['A'..'Z'];
For Location := 1 to Length(St) Do
If St[Location] IN Valid_Ch
Then St[Location] := CHR(ORD(St[Location]) + 32);
{ Exercise: write a single structure which will convert upper
case letters to lower case AND visa-versa }
Type
Bad_letters = Set of 'A'..'z';
Var
Remove: Bad_letters;
Good_string: String[80];
LCV: Integer;
Remove := ['a', 'b', 'c'];
Readln(X);
Good_string := '';
For LCV := 1 to Len(X) Do
If NOT(X[LC] IN Remove)
Then Good_string := Good_string + X[LCV];
Const
Blank = ' ';
Dec_pt = '.';
Char_Zero = '0';
Var
St, New: String[80];
Location, Mid: 1..80;
Valid_Ch: Set of Char;
Len, Error: Integer;
First_real, Second_real: Real;
Real_string, Int_string, Dec_string: String[30];
Readln(First_real);
STR(First_real :0:8, Real_string);
Location := POS(Dec_pt, Real_string);
Len := Length(Real_string);
Int_string := COPY(Real_string, 1, Location - 1);
Dec_string := COPY(Real_string, Location + 1, Len - Location);
Location := Length(Dec_string); { strip trailing zeros }
While Dec_String[Location] = Char_Zero Do
Location := PRED(Location);
{ adjust the location marker if decimal string is all 0s }
If Location = 0
Then Location := 1;
Dec_string := COPY(Dec_string, 1, Location);
Real_string := Dec_string + Dec_pt + Int_string;
VAL(Real_string, Second_real, Error);
Const
Field_separator = '/';
Blank = ' ';
Var
St: String[80];
Int_string: String[30];
Value, Sum: Integer;
Location: 1..80;
Len, Error: 0..80;
St := St + Field_separator; { add mark to terminate last field }
Sum := 0
While Length(St) <> 0 Do
Begin
{ extract one field }
Location := POS(Field_separator, St);
Int_string := COPY(St, 1, Location - 1);
DELETE(St, 1, Location);
{ trim leading/trailing spaces }
Location := 1;
While Int_string[Location] = Blank Do
Location := SUCC(Location);
DELETE(Int_string, 1, Location - 1);
Len := Length(Int_string);
Location := Len;
While Int_string[Location] = Blank Do
Location := PRED(Location);
DELETE(Int_string, Location + 1, Len - Location);
{ convert to numeric type, print and add }
VAL(Int_string, Value, Error);
Writeln(Value :4);
Sum := Sum + Value
End;
Writeln('----');
Writeln(Sum :4)
What can go wrong here? Empty fields can cause runaway string operations if
we are not careful about checking for unusual cases. See an example.
Const
Field_separator = '/';
Blank = ' ';
Var
St: String[80];
Int_string: String[30];
Value, Sum: Integer;
Location: 1..80;
Len, Error: 0..80;
St := St + Field_separator; { add mark to terminate last field }
Sum := 0;
While Length(St) <> 0 Do
Begin
{ extract one field }
Location := POS(Field_separator, St);
Int_string := COPY(St, 1, Location - 1); { Int_string could be null }
DELETE(St, 1, Location);
{ trim leading/trailing spaces }
Len := Length(Int_string);
Location := 1;
While (Int_string[Location] = Blank) and (Location < Len) Do
Location := SUCC(Location);
DELETE(Int_string, 1, Location - 1);
Len := Length(Int_string);
Location := Len;
While (Int_string[Location] = Blank) and (Location > 0) Do
Location := PRED(Location);
DELETE(Int_string, Location + 1, Len - Location);
{ convert to numeric type, print and add }
VAL(Int_string, Value, Error);
If Error = 0
Then
Begin
Writeln(Value :4);
Sum := Sum + Value
End
End;
Writeln('----');
Writeln(Sum :4)
Program Parse;
{ This program demonstrates how to "parse" a string and separate out the
important data values contained in it. It is assumed that Line is a
string which contains integer values separated by /. Typical strings
might be 34 / 45 / 789 or / / 3 / 48/ 79/ The objective of the
program is to separate out all the individual integer values from the
string and process them (for example, add them up).
The basic idea behind the processing is to form a WHILE loop controlled
by the length of the string. The string will contract as the loop runs
because pieces will be pulled from the front of the string.
While length string > 0 Do
1. delete all lead spaces in string
2. find the location of the first / in the string
3. copy out from the string all characters from the beginning of
the string up to and including / -- store this chunk of the
string in "Piece"
4. delete the characters in Piece from the original string
5. counting backwards from the end of Piece, find the last digit
in Piece (if there indeed is one)
6. copy out of Piece the portion of Piece which contains only
digits (or possibly embedded non-digits)
7. convert this string to a numeric value using VAL
8. if the conversion is successful, print this value and add it
to Sum
After the loop quits, print the sum of all the numeric values
successfully converted from the original string }
Uses
crt;
Const
Line = ' / 23 / 478 /8/ 8z7 / 2.3 /xvt/ 987 / 5996 ';
Sep = '/';
Space = ' ';
Digits: Set of Char = ['0'..'9'];
Var
X: String;
N, Error, Sum: Integer;
Piece: String;
Loc: Integer;
Begin
Clrscr;
X := Line;
X := X + Sep; { Ensure that X ends with a / }
Sum := 0;
While Length(X) > 0 Do
Begin
{ Delete the lead spaces from the string X }
While Pos(Space, X) = 1 Do
Delete(X, 1, 1);
{ Delete any lead non-digit characters. Yes, this would also
delete lead spaces - but this is only an example! }
While NOT(X[1] in Digits) AND (Length(X) >= 1) Do
Delete(X, 1, 1);
{ Find the location of the first / in X; copy all characters
in X from the beginning of X up to and including the / into
the string Piece; delete these characters from the beginning of X }
Loc := Pos(Sep, X);
Piece := COPY(X, 1, Loc);
Delete(X, 1, Loc);
{ Count backwards from the end of Piece until a digit is found }
While NOT(Piece[Loc] in Digits) AND (Loc > 0) Do
Loc := Loc - 1;
{ Make a new copy of Piece which consists of characters from the
beginning of Piece to the place where a digit was located; it's
possible that Loc = 0 if no digits were encountered in Piece
(for example, if the field consists only of spaces or of non-
digit characters) }
Piece := COPY(Piece, 1, Loc);
{ The following code can be used to see how Piece is formed for
each field separated by /
If Length(Piece) > 0
Then Writeln('piece = ''', piece, '''')
Else Writeln('piece = null'); }
{ Convert Piece to an integer value N }
VAL(Piece, N, Error);
{ If Piece is null or contains garbage, ignore N (that is, when
Error > 0); otherwise, add N to Sum and print N }
If Error = 0
Then
Begin
Writeln(N :4);
Sum := Sum + N
End;
End; { WHILE }
Writeln('----');
Writeln(Sum :4);
Readln;
End.