2
votes

I am working on database project in SWI-Prolog. Problem is that i want to work with names of Sportsmen which i read from input. I need to save their names with capital letters, but prolog interprets these as variables. Any ideas how to fix this?

4
If you look at the SWI documentation, there is quite a bit of support for character and string manipulation and I/O. There is, for example, to_upper/2 or to_lower/2 for converting a character to/from upper and lower case. There are also predicates such as read_line_to_codes/2 which will read a "raw" input line rather than attempting to interpret it as a Prolog term (which is what read/1 does). You might also want to look at atom_codes/2. Have a look at those, give something a try, and see if you have more specific questions afterwards. - lurker
In my answer I use code_type/2 which has the lower/1, to_lower/1, upper/1, and to_upper/1 options of the second argument. char_type/2 works the same way, but on single-character atoms. SWI has quite some support for case-conversion :-) - Wouter Beek

4 Answers

2
votes

I would use code_type/2 to ensure that any entered name starts with a capital letter.

Since you want to allow a user to enter a name with a letter that is either lower- or uppercase, I do the case conversion on the codes list that I read with read_line_to_codes/2.

Since you want to store the names in a database, I use dynamic/1 to declare that I will be adding some sportsname/1 entries, and I use assert/1 to add a specific name to the database.

Here is the code:

:- dynamic(sportsname/1).

:- initialization(input).

input:-
  repeat,
  format(user_output, 'Please enter a name (or type `quit`):\n', []),
  read_line_to_codes(user_input, Codes1),
  (
    atom_codes(quit, Codes1)
  ->
    !, true
  ;
    capitalize(Codes1, Codes2)
  ->
    atom_codes(Name, Codes2),
    assert(sportsname(Name)),
    format(current_output, 'Sportsname ~a writen to database.\n', [Name]),
    fail
  ;
    fail
  ).

capitalize([], []).
capitalize([H1|T], [H2|T]):-
  code_type(H2, to_upper(H1)).

Example of use:

$ swipl sport_names.pl
Please enter a name (or type `quit`):
|: john
Sportsname John writen to database.
Please enter a name (or type `quit`):
|: James
Sportsname James writen to database.
Please enter a name (or type `quit`):
|: suzan
Sportsname Suzan writen to database.
Please enter a name (or type `quit`):
|: quit

?- sportsname(X).
X = 'John' ;
X = 'James' ;
X = 'Suzan'.

Hope this helps!

1
votes

Use either quoted atoms...

?- atom('X').
true.

?- 'X' = 'Y'.
false.

... or strings:

?- X = "Foo!".
X = [70, 111, 111, 33].

(strings are represented as lists of codepoints, in this case ASCII ones). Quoted atoms are much easier to work with.

1
votes

I don't know how implementation independent this code is, but this works for me in SWI-Prolog:

read_string(String) :-
    current_input(Input),
    read_line_to_codes(Input, Codes),
    string_codes(String, Codes).

Sample input and output:

?- read_string(X).
|: Test!
X = "Test!".
0
votes

Just quote any string that need to be read by Prolog, regardless to the case you find in the database... Beware to escaping: for instance

?- write('O\'Neal').
O'Neal

?- read(X).
|: 'O\'Neal'.
X = 'O\'Neal'.