You are on page 1of 12

TURBO PASCAL STRINGS

Strings are not a supported data type of standard Pascal, and so we must reply on the implementation of string handling afforded with various versions of Pascal. In this course, we use the string definitions and manipulation in Borland Turbo Pascal V7.0. 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]; Employee_name = String[30]; Var Infile_name: File_name; Emp_name: Employee_name; Line: String; { max length = 14 }

{ 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: 1. STRING ASSIGNMENT SYMBOL: := 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_namewould be 'A:\OUTPUT\PROG' which may not be what we expected! Also, Infile_name[2] = ':' and Infile_name[11] = 'P'. 2. STRING CONCATENATION ("GLUE") SYMBOL: + Example:
Infile_name := 'A:\' + 'PROG006' + '.OUT';

3. INDIVIDUAL STRING ELEMENTS SYMBOL: St[n]

Example: Writeln(Infile_name[3]); causes the third character of Infile_name to be printed. 4. STRING COMPARISON SYMBOLS: =, <, <=, >,
>=, <>

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' 'Z' < 'a' 'a' < 'B' 'TURBO' ='TURBO' 'TURBO' = 'Turbo' 'turbo ' = 'turbo' 'turbo ' > 'turbo' TRUE TRUE FALSE TRUE FALSE FALSE TRUE

STRING FUNCTIONS 5. LENGTH Syntax: Length(St) Returns the current length of the string St in range 0..255. Example:
Var St: String[20]; Len: Integer; { make St the null string } { Len now has value 0 } { Len now has value 5 }

St := ''; Len := Length(St); St := St + 'Begin'; Len := Length(St);

6. POSITION Syntax: 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 Patternis 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 If Pattern If Pattern

= 'SIP', = =

then Location = 7. 'is', then Location = 0. ' ', then Location = 0.


Start, Number)

7. COPY Syntax: Copy(St,

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 If Start

= 12, =

then Part 5 and Number

= ''. = 20,

then Part

= 'ISSIPPI'.

STRING PROCEDURES 8. DELETE Syntax: 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 If Start

does not change. = 2 and Number = 20, then Delete(St, Start, Number) changes St to 'M'. 9. INSERT Syntax: Insert(Pattern,
Insert Target, Position)

= 15, St

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, Insert(Part, Target, Position)

then

changes Target to 'MISSISabcdefghijklSI'. If Position = 70, then Target = 'MISSISSIPPIabcdefghi'. 10. VAL Syntax: 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); Val(Num_str, I_Num, Error); Num_str := '256,78'; Val(Num_str, R_Num, Error); Num_str := '23456'; Val(Num_str, I_Num, Error); Val(Num_str, R_Num, Error); {R_Num = 23.45, Error = 0} {Error = 3; R_Num stays 23.45 } {R_Num = 23.45, Error = 4} {I_Num = 23456, Error = 0} {R_Num = 23456.0, Error = 0}

11. STR Syntax: 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); R_num := 2345.678; Str(R_num :0:6, Result); Str(R_num :0:1, Result); Str(R_num :10:2, Result); Str(R_num, Result); 2.3456780000E+03'} {Result = '-345'} {Result {Result {Result {Result = = = = '2345.678000'} '2345.7'} ' 2345.68'} '

EXAMPLES OF THE USE OF THESE FUNCTIONS AND PROCEDURES:


Const Space = ' '; Var St, First, Last: String[80]; Position, Len: Integer; Remove: Char;

1. Remove all lead blanks from a string


2. 3. St := ' now is the time'; 4. While POS(Space, St) = 1 Do 5. Delete(St, 1, 1);

6. Reverse the order of names in 'Smith John'


7. 8. St := 'Smith John'; 9. Location := POS(Space, St); { Location = 6 } 10. Len := Length(St); { Len = 10 } 11. Last := COPY(St, 1, Location - 1); { Last = 'SMITH'} 12. First := COPY(St, Location + 1, Len - Location); 13. St := First + Space + Last;

14. Remove all specified characters from a string


15. 16. 17. 18. 19. 20. 21. 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 22. Insert a blank every fifth character in a string
23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 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];

36. Build a string from null, reverse to that of a given string


37. 38. New := ''; 39. For Location := Length(St) downto 1 Do 40. New := New + St[Location];

41. Count number of vowels in a string (use set statement)


42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 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);

55. Convert all lower case letters in a string to upper case and visa-versa!
{ 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 }

69. Remove all the 'a', 'b' and 'c' from a given string:
70. 71. Type 72. Bad_letters = Set of 'A'..'z'; 73.

74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84.

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];

85. Receive a real value; convert it to another real value with the integer and decimal parts interchanged:
86. 87. Const 88. Blank = ' '; 89. Dec_pt = '.'; 90. Char_Zero = '0'; 91. 92. Var 93. St, New: String[80]; 94. Location, Mid: 1..80; 95. Valid_Ch: Set of Char; 96. Len, Error: Integer; 97. First_real, Second_real: Real; 98. Real_string, Int_string, Dec_string: String[30]; 99. 100. Readln(First_real); 101. STR(First_real :0:8, Real_string); 102. Location := POS(Dec_pt, Real_string); 103. Len := Length(Real_string); 104. Int_string := COPY(Real_string, 1, Location - 1); 105. Dec_string := COPY(Real_string, Location + 1, Len Location); 106. 107. Location := Length(Dec_string); { strip trailing zeros } 108. While Dec_String[Location] = Char_Zero Do 109. Location := PRED(Location); 110. 111. { adjust the location marker if decimal string is all 0s } 112. If Location = 0 113. Then Location := 1; 114. 115. Dec_string := COPY(Dec_string, 1, Location); 116. Real_string := Dec_string + Dec_pt + Int_string; 117. VAL(Real_string, Second_real, Error);

118. Separate out pieces of a string from each other and process these pieces (they could be integer values, etc.) This is an example of a general problem called parsing a string. a. Receive a string of integers separated by slashes (possibly with leading/trailing spaces); extract the numbers, print them one per line, and calculate their sum; no "field" is empty:
b. c. Const d. Field_separator = '/'; e. Blank = ' '; f.

g. Var h. St: String[80]; i. Int_string: String[30]; j. Value, Sum: Integer; k. Location: 1..80; l. Len, Error: 0..80; m. n. o. St := St + Field_separator; { add mark to terminate last field } p. Sum := 0 q. While Length(St) <> 0 Do r. Begin s. t. u. { extract one field } v. w. Location := POS(Field_separator, St); x. Int_string := COPY(St, 1, Location - 1); y. DELETE(St, 1, Location); z. aa. bb. { trim leading/trailing spaces } cc. dd. Location := 1; ee. While Int_string[Location] = Blank Do ff. Location := SUCC(Location); gg. DELETE(Int_string, 1, Location - 1); hh. Len := Length(Int_string); ii. Location := Len; jj. While Int_string[Location] = Blank Do kk. Location := PRED(Location); ll. DELETE(Int_string, Location + 1, Len - Location); mm. nn. oo. { convert to numeric type, print and add } pp. qq. VAL(Int_string, Value, Error); rr. Writeln(Value :4); ss. Sum := Sum + Value tt. End; uu. Writeln('----'); vv. 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. ww. Same as (a), except allow "empty" fields, and leading/trailing slashes:
xx. yy. zz. aaa. bbb. ccc. ddd. eee. fff. Const Field_separator = '/'; Blank = ' '; Var St: String[80]; Int_string: String[30]; Value, Sum: Integer;

ggg. Location: 1..80; hhh. Len, Error: 0..80; iii. jjj. kkk. St := St + Field_separator; { add mark to terminate last field } lll. Sum := 0; mmm. While Length(St) <> 0 Do nnn. Begin ooo. ppp. qqq. { extract one field } rrr. sss. Location := POS(Field_separator, St); ttt. Int_string := COPY(St, 1, Location - 1); { Int_string could be null } uuu. DELETE(St, 1, Location); vvv. www. xxx. { trim leading/trailing spaces } yyy. zzz. Len := Length(Int_string); aaaa. Location := 1; bbbb. While (Int_string[Location] = Blank) and (Location < Len) Do cccc. Location := SUCC(Location); dddd. DELETE(Int_string, 1, Location - 1); eeee. Len := Length(Int_string); ffff. Location := Len; gggg. While (Int_string[Location] = Blank) and (Location > 0) Do hhhh. Location := PRED(Location); iiii. DELETE(Int_string, Location + 1, Len - Location); jjjj. kkkk. llll. { convert to numeric type, print and add } mmmm. nnnn. VAL(Int_string, Value, Error); oooo. If Error = 0 pppp. Then qqqq. Begin rrrr. Writeln(Value :4); ssss. Sum := Sum + Value tttt. End uuuu. End; vvvv. Writeln('----'); wwww. Writeln(Sum :4)

xxxx. Same as (b), except handle "dirty" fields with non-blanks before/after the numbers, as well as invalid data:
yyyy. zzzz. Program Parse; aaaaa. bbbbb. { This program demonstrates how to "parse" a string and separate out the ccccc. important data values contained in it. It is assumed that Line is a ddddd. string which contains integer values separated by /. Typical strings eeeee. might be 34 / 45 / 789 or / / 3 / 48/ 79/ The objective of the

fffff. program is to separate out all the individual integer values from the ggggg. string and process them (for example, add them up). hhhhh. iiiii. The basic idea behind the processing is to form a WHILE loop controlled jjjjj. by the length of the string. The string will contract as the loop runs kkkkk. because pieces will be pulled from the front of the string. lllll. mmmmm. While length string > 0 Do nnnnn. 1. delete all lead spaces in string ooooo. 2. find the location of the first / in the string ppppp. 3. copy out from the string all characters from the beginning of qqqqq. the string up to and including / -- store this chunk of the rrrrr. string in "Piece" sssss. 4. delete the characters in Piece from the original string ttttt. 5. counting backwards from the end of Piece, find the last digit uuuuu. in Piece (if there indeed is one) vvvvv. 6. copy out of Piece the portion of Piece which contains only wwwww. digits (or possibly embedded non-digits) xxxxx. 7. convert this string to a numeric value using VAL yyyyy. 8. if the conversion is successful, print this value and add it zzzzz. to Sum aaaaaa. bbbbbb. After the loop quits, print the sum of all the numeric values cccccc. successfully converted from the original string } dddddd. eeeeee. Uses ffffff. crt; gggggg. hhhhhh. Const iiiiii. Line = ' / 23 / 478 /8/ 8z7 / 2.3 /xvt/ 987 / 5996 '; jjjjjj. Sep = '/'; kkkkkk. Space = ' '; llllll. Digits: Set of Char = ['0'..'9']; mmmmmm. nnnnnn. Var oooooo. X: String; pppppp. N, Error, Sum: Integer; qqqqqq. Piece: String; rrrrrr. Loc: Integer; ssssss. tttttt. Begin uuuuuu. Clrscr; vvvvvv. wwwwww. X := Line; xxxxxx. X := X + Sep; { Ensure that X ends with a / } yyyyyy. Sum := 0;

zzzzzz. aaaaaaa. While Length(X) > 0 Do bbbbbbb. Begin ccccccc. ddddddd. eeeeeee. { Delete the lead spaces from the string X } fffffff. ggggggg. While Pos(Space, X) = 1 Do hhhhhhh. Delete(X, 1, 1); iiiiiii. jjjjjjj. kkkkkkk. { Delete any lead non-digit characters. Yes, this would also lllllll. delete lead spaces - but this is only an example! } mmmmmmm. nnnnnnn. While NOT(X[1] in Digits) AND (Length(X) >= 1) Do ooooooo. Delete(X, 1, 1); ppppppp. qqqqqqq. rrrrrrr. { Find the location of the first / in X; copy all characters sssssss. in X from the beginning of X up to and including the / into ttttttt. the string Piece; delete these characters from the beginning of X } uuuuuuu. vvvvvvv. Loc := Pos(Sep, X); wwwwwww. Piece := COPY(X, 1, Loc); xxxxxxx. Delete(X, 1, Loc); yyyyyyy. zzzzzzz. aaaaaaaa. { Count backwards from the end of Piece until a digit is found } bbbbbbbb. cccccccc. While NOT(Piece[Loc] in Digits) AND (Loc > 0) Do dddddddd. Loc := Loc - 1; eeeeeeee. ffffffff. gggggggg. { Make a new copy of Piece which consists of characters from the hhhhhhhh. beginning of Piece to the place where a digit was located; it's iiiiiiii. possible that Loc = 0 if no digits were encountered in Piece jjjjjjjj. (for example, if the field consists only of spaces or of nonkkkkkkkk. digit characters) } llllllll. mmmmmmmm. Piece := COPY(Piece, 1, Loc); nnnnnnnn. oooooooo. pppppppp. { The following code can be used to see how Piece is formed for qqqqqqqq. each field separated by / rrrrrrrr. ssssssss. If Length(Piece) > 0 tttttttt. Then Writeln('piece = ''', piece, '''')

uuuuuuuu. Else Writeln('piece = null'); } vvvvvvvv. wwwwwwww. xxxxxxxx. { Convert Piece to an integer value N } yyyyyyyy. zzzzzzzz. VAL(Piece, N, Error); aaaaaaaaa. bbbbbbbbb. ccccccccc. { If Piece is null or contains garbage, ignore N (that is, when ddddddddd. Error > 0); otherwise, add N to Sum and print N } eeeeeeeee. fffffffff. If Error = 0 ggggggggg. Then hhhhhhhhh. Begin iiiiiiiii. Writeln(N :4); jjjjjjjjj. Sum := Sum + N kkkkkkkkk. End; lllllllll. mmmmmmmmm. End; { WHILE } nnnnnnnnn. ooooooooo. Writeln('----'); ppppppppp. Writeln(Sum :4); qqqqqqqqq. Readln; End.