Text: length, copy, pos and upcase
A string is a row of characters you can measure, slice and search: length, copy, pos, upcase and the plus sign that joins two pieces.
A string is characters in a row
Text is stored as a string, and the characters can be reached by number: text[1] is the first character of text. Our strings count from one, so the last character is text[length(text)].
The two common mistakes both come from other languages: the index starts at one rather than zero, and a single character is a char with single quotes around it, not a string of length one.
Two strings compare with =, < and the rest, letter by letter. That is why sorting a list of names needs no extra call: the comparison already does the sensible thing.
The numbering is not arbitrary: it is the convention Pascal inherited, and it means a position and a length are different numbers. The length of Pascal is 6, and the last valid index is also 6, but for a substring the two stop agreeing, which is where beginners lose a character.
The four calls worth knowing
length(text) gives the number of characters. copy(text, start, count) returns a slice beginning at start, and asking for more characters than exist simply stops at the end, returning an empty string if the start is past it.
pos(needle, text) returns the position of the first occurrence, or 0 when the needle is not there — a zero you have to test for, since it is not an error. The search is case sensitive, so pos('a', 'Pascal') and pos('A', 'Pascal') give different answers.
upcase takes one character and returns its capital form. It is not a whole-string function, so capitalising a word means a loop over its characters.
Building text
The plus sign joins two strings into one new string. It does not modify either side, so building a line by repeated + is fine and costs nothing in clarity.
Numbers join text in the same way inside writeln, but assigning a number into a string variable is a different matter: concatenation with + needs both sides to be text already.
Joining is cheap to read, and it does copy the text underneath. A loop that appends one character at a time to a long string therefore does more work than it looks, because each + builds a new block. For the short strings in this course that is invisible; for a large report, collect the pieces in an array and join once.
Measure, slice, search
program Main;
var
word: string;
begin
word := 'Pascal';
writeln(length(word));
writeln(copy(word, 1, 3));
writeln(pos('sc', word));
writeln(upcase(word[1]));
end.Bytes, characters and the length trap
The string in these examples is an AnsiString: a counted block of bytes, numbered from one. length reports the number of bytes, not the number of visible characters. Plain ASCII text has one byte per character, which is why the count matches what you see; an accented letter or an emoji can take two or more bytes, so text[2] may land in the middle of one character.
copy slices by byte position and pos returns a byte position, and both follow the same rule. Concatenation with + allocates a new string and copies both sides into it, so the original is unchanged. For the lessons here the text is ASCII and the two ideas agree, but a program that accepts names from outside has to decide which kind of count it means.
A worked slice
Take word holding the text Pascal and follow copy(word, 2, 3). The start is position 2, the character a; the count is three, so the slice covers positions 2, 3 and 4 — asc. The P at position 1 is left out, and the final l is beyond the count. Reading the call as “start here, take this many” prevents most slicing errors.
Now search for the letters sc. pos returns 3, because the s sits at position 3, and copy(word, 3, 2) therefore starts at 3 and takes two characters, giving sc. If the search fails, pos returns 0, and the same call would start before the string and return an empty result. Test the zero before you slice.
Three text mistakes to watch for: starting an index at zero, which is outside the string; using the 0 from a failed pos as a start position for copy; and handing a whole word to upcase, which expects one character. Test the pos result before you slice with it, and loop over the characters when a word needs capitalising.
Try these next
- Change the word to
Graceand predict the length, the first three letters and the position ofac. - Search for a text that is not present and print the result inside a sentence.
- Write a loop that prints every letter of the word on its own line.
Measure, slice and search one word
Run it, then change the word to your own name and predict the length, the first three letters and the position the search will find.
Change the search text in pos to something that is not there and run again. The zero that comes back is the not-found answer, not an error.
Initials from a full name
Run it, then change the name to `Grace Hopper` and predict the initials and surname before running. What would happen with a middle name?
Check what you learned
One question at a time. A wrong answer explains itself — take another go.
Part 1 of 5
Which expression gives the first character of a string variable?
