Previous | Table of Contents | Next |
6.3.4.4. Strings
Any sequence of ASCII characters between double quote marks ( ) forms a Prolog string. As in most other languages, two double quotes in the sequence represent a double quote inside the string.
Prolog strings can be input (in queries and programs) as double-quoted sequences, but they are represented internally as lists of integers (the integers being the ASCII character codes of the characters of the string). That is also how they are output in answer substitutions. Thus the query Firstname = Jamie returns the substitution Firstname = [74,97,109,105,101] because those five numbers are the codes of the five characters of that name. This representation is useful for manipulation using standard Prolog list-processing predicates. No special string-processing package is needed.
What is the relationship between these character strings and the single-quoted sequences of characters we have met before, for instance, Hello world? The latter are actually constants and are represented internally in the same way as other constants, such as a and 54. The single quotes allow us to use a constant name that has spaces or symbolic characters or begins with an uppercase letter (which would normally get it interpreted as a variable). These are what we normally use when we want to, for instance, write out some message to the user; write(Hello world) is thus a request to Prolog to write out the name of a constant, whose name happens to be Hello world.
We can move back and forth between the name of a constant and its Prolog string version using the name predicate. The query name(archy, X) returns the substitution X = [97,114,99,104,121], and conversely name(Y, [97,114,99,104,121]) returns Y = archy. This works for integers as well as constants, so that name(42, Answer) returns Answer = [52,50], those being the ASCII codes for the characters 4 and 2.
Consider the following predicate:
newword(Word, Number, Newword) :- name(Word, Wordstring), Wordstring = [Firstchar|Restchars], Cap is Firstchar - 32, name(Number, Numberstring), append([Cap|Restchars], Numberstring, Newwordstring), name(Newword, Newwordstring).
The predicate essentially capitalizes the string corresponding to first argument (which is supposed to be an alphanumeric constant), appends the string of the second (numeric) argument to it, and transforms the whole string back into a constant name. The result is that a query such as newword(car, 54, X) returns the substitution X = Car54.
Input and output are somewhat variable from one dialect of Prolog to another, but most dialects use some variant of the Edinburgh Prolog standard library of predicates. In general, I/O predicates are evaluated by Prolog once, as soon as they are called, and never take any action on backtracking.
6.3.5.1. Term I/O
The two simplest I/O predicates are read and write. Because they take terms as arguments, they are referred to as term I/O predicates. We have already encountered write, which simply writes out a standard ASCII representation of the term it is given. We have also encountered the specialized predicate nl, which writes the system newline character.
read(X) reads a Prolog term from the input and instantiates X to that term. (X must be uninstantiated when read is called.) The term that is read must be a valid Prolog term and must be terminated by a period, as a Prolog clause is. It is therefore not advisable to use read for interaction with a naive user: Prolog waits until the user types a period, and if the syntax of the term is wrong, it gives a compiler-like (that is, not very helpful) error message. It is better to use the character I/O described later for most interactions.
read is useful, however, for simple programs and for reading preformatted files of input terms. Section 6.5, Examples, gives a program that reads a file of debugging output from a C program and checks it to see if the C program had any memory leaks.
6.3.5.2. Character I/O
Character I/O is done with the two predicates get0(X) and put(X). Both work with integers as character codes, get0 reading a character and put writing one. Here are two useful predicates that can be written with these character I/O predicates:
readstring(X) :- get0(C), readstring1(C, X). readstring1(C, []) :- newlinechar(C), !. readstring1(C, [C|Cs]) :- readstring(Cs). writestring([]) :- nl. writestring([C|Cs]) :- put(C), writestring(Cs).
The first reads a string from input up to the first newline character and returns a string consisting of all those characters except the final new-line. (You have to program the newlinechar predicate yourself because this character varies from computer to computer; on UNIX systems, newlinechar(10) is usually correct.) The second predicate writes a string on output, terminating it with a newline character.
On end-of-file conditions, Prologs can be variable in what they report. (Check your Prolog manual.) Edinburgh Prologs usually return -1 as the character read after end-of-file by get0 and the constant end_of_file as the term read by read after end-of-file. Further reads after end-of-file may result in runtime errors. A safer version of readstring, which reports on whether it has reached the end of the file on its last read, is the following:
readstring(X, EOFflag) :- get0(C), readstring1(C, X, EOFflag). readstring1(-1, [], EOFflag) :- !, EOFflag = eof. readstring1(C, [], EOFflag) :- newlinechar(C), !, EOFflag = not_eof. readstring1(C, [C|Cs], EOFflag) :- readstring(Cs, EOFflag).
Previous | Table of Contents | Next |