- 序言教程
- 序言 - 主页
- Prolog - 简介
- Prolog - 环境设置
- Prolog - 你好世界
- Prolog - 基础知识
- Prolog - 关系
- Prolog - 数据对象
- Prolog - 运算符
- 循环与决策
- 连接词和析取词
- Prolog - 列表
- 递归和结构
- Prolog - 回溯
- Prolog - 不同与不同
- Prolog - 输入和输出
- Prolog - 内置谓词
- 树数据结构(案例研究)
- Prolog - 示例
- Prolog - 基本程序
- Prolog - 剪切示例
- 河内塔问题
- Prolog - 链接列表
- 猴子和香蕉问题
- Prolog 有用资源
- Prolog - 快速指南
- Prolog - 有用的资源
- Prolog - 讨论
Prolog - 输入和输出
在本章中,我们将看到一些通过 prolog 处理输入和输出的技术。我们将使用一些内置谓词来完成这些任务,并查看文件处理技术。
将详细讨论以下主题 -
处理输入和输出
使用 Prolog 处理文件
使用一些外部文件来读取行和术语
输入和输出的字符操作
构造和分解Atomics
查阅 prolog 文件以了解其他 prolog 程序技术。
处理输入和输出
到目前为止,我们已经看到我们可以编写一个程序并在控制台上执行查询。在某些情况下,我们会在控制台上打印一些用 prolog 代码编写的内容。因此,在这里我们将使用 prolog 更详细地了解写入和读取任务。这就是输入和输出处理技术。
write() 谓词
要写入输出,我们可以使用write()谓词。该谓词将参数作为输入,默认将内容写入控制台。write() 也可以写入文件。让我们看一些 write() 函数的示例。
程序
| ?- write(56). 56 yes | ?- write('hello'). hello yes | ?- write('hello'),nl,write('world'). hello world yes | ?- write("ABCDE") . [65,66,67,68,69] yes
从上面的例子中,我们可以看到 write() 谓词可以将内容写入控制台。我们可以使用“nl”来创建一个新行。从这个例子中可以清楚地看出,如果我们想在控制台上打印一些字符串,我们必须使用单引号('string')。但如果我们使用双引号(“字符串”),那么它将返回一个 ASCII 值列表。
read() 谓词
read() 谓词用于从控制台读取。用户可以在控制台中编写一些内容,该内容可以作为输入并进行处理。read() 通常用于从控制台读取,但也可以用于从文件读取。现在让我们看一个例子来了解 read() 是如何工作的。
程序
cube :- write('Write a number: '), read(Number), process(Number). process(stop) :- !. process(Number) :- C is Number * Number * Number, write('Cube of '),write(Number),write(': '),write(C),nl, cube.
输出
| ?- [read_write]. compiling D:/TP Prolog/Sample_Codes/read_write.pl for byte code... D:/TP Prolog/Sample_Codes/read_write.pl compiled, 9 lines read - 1226 bytes written, 12 ms (15 ms) yes | ?- cube. Write a number: 2. Cube of 2: 8 Write a number: 10. Cube of 10: 1000 Write a number: 12. Cube of 12: 1728 Write a number: 8. Cube of 8: 512 Write a number: stop . (31 ms) yes | ?-
tab() 谓词
tab() 是一个附加谓词,可用于在我们编写内容时放置一些空格。因此它接受一个数字作为参数,并打印那么多的空格。
程序
| ?- write('hello'),tab(15),write('world'). hello world yes | ?- write('We'),tab(5),write('will'),tab(5),write('use'),tab(5),write('tabs'). We will use tabs yes | ?-
读/写文件
在本节中,我们将了解如何使用文件读取和写入文件。有一些内置谓词可用于从文件读取和写入文件。
告诉和告诉
如果我们想写入除控制台之外的文件,我们可以编写tell()谓词。该tell()谓词将文件名作为参数。如果该文件不存在,则创建一个新文件并写入其中。该文件将被打开,直到我们编写告诉命令。我们可以使用tell()打开多个文件。当调用告诉时,所有文件将被关闭。
序言命令
| ?- told('myFile.txt'). uncaught exception: error(existence_error(procedure,told/1),top_level/0) | ?- told("myFile.txt"). uncaught exception: error(existence_error(procedure,told/1),top_level/0) | ?- tell('myFile.txt'). yes | ?- tell('myFile.txt'). yes | ?- write('Hello World'). yes | ?- write(' Writing into a file'),tab(5),write('myFile.txt'),nl. yes | ?- write("Write some ASCII values"). yes | ?- told. yes | ?-
输出(myFile.txt)
Hello World Writing into a file myFile.txt [87,114,105,116,101,32,115,111,109,101,32,65,83,67,73,73,32,118,97,108,117,101,115]
同样,我们也可以从文件中读取。让我们看一些从文件读取的示例。
所见与所见
当我们想要从文件而不是键盘读取时,我们必须更改当前的输入流。所以我们可以使用 see() 谓词。这将以文件名作为输入。当读操作完成后,我们将使用seen命令。
示例文件 (sample_predicate.txt)
likes(lili, cat). likes(jhon,dog).
输出
| ?- see('sample_predicate.txt'), read(X), read(Y), seen, read(Z). the_end. X = end_of_file Y = end_of_file Z = the_end yes | ?-
因此,从这个例子中,我们可以看到使用 see() 谓词我们可以从文件中读取。现在使用seen命令后,控制权再次转移到控制台。所以最后它从控制台获取输入。
处理条款文件
我们已经了解了如何读取文件的特定内容(几行)。现在,如果我们想要读取/处理文件的所有内容,我们需要编写一个子句来处理文件(process_file),直到到达文件末尾。
程序
process_file :- read(Line), Line \== end_of_file, % when Line is not not end of file, call process. process(Line). process_file :- !. % use cut to stop backtracking process(Line):- %this will print the line into the console write(Line),nl, process_file.
示例文件 (sample_predicate.txt)
likes(lili, cat). likes(jhon,dog). domestic(dog). domestic(cat).
输出
| ?- [process_file]. compiling D:/TP Prolog/Sample_Codes/process_file.pl for byte code... D:/TP Prolog/Sample_Codes/process_file.pl compiled, 9 lines read - 774 bytes written, 23 ms yes | ?- see('sample_predicate.txt'), process_file, seen. likes(lili,cat) likes(jhon,dog) domestic(dog) domestic(cat) true ? (15 ms) yes | ?-
操纵字符
使用 read() 和 write() 我们可以读取或写入Atomics、谓词、字符串等的值。现在在本节中我们将看到如何将单个字符写入当前输出流,或如何从当前输入流读取。因此,有一些预定义的谓词来完成这些任务。
put(C) 和 put_char(C) 谓词
我们可以使用 put(C) 一次将一个字符写入当前输出流。输出流可以是文件或控制台。在其他版本的 Prolog(如 SWI prolog)中,这个 C 可以是字符或 ASCII 代码,但在 GNU prolog 中,它仅支持 ASCII 值。要使用字符而不是 ASCII,我们可以使用 put_char(C)。
程序
| ?- put(97),put(98),put(99),put(100),put(101). abcde yes | ?- put(97),put(66),put(99),put(100),put(101). aBcde (15 ms) yes | ?- put(65),put(66),put(99),put(100),put(101). ABcde yes | ?-put_char('h'),put_char('e'),put_char('l'),put_char('l'),put_char('o'). hello yes | ?-
get_char(C) 和 get_code(C) 谓词
要从当前输入流读取单个字符,我们可以使用 get_char(C) 谓词。这将采取角色。如果我们想要 ASCII 代码,我们可以使用 get_code(C)。
程序
| ?- get_char(X). A. X = 'A' yes uncaught exception: error(syntax_error('user_input:6 (char:689) expression expected'),read_term/3) | ?- get_code(X). A. X = 65 yes uncaught exception: error(syntax_error('user_input:7 (char:14) expression expected'),read_term/3) | ?-
构造Atomics
Atomics构造意味着我们可以从一个字符列表中创建一个Atomics,或者从一个 ASCII 值列表中我们也可以创建一个Atomics。为此,我们必须使用atom_chars() 和atom_codes() 谓词。在这两种情况下,第一个参数都是一个变量,第二个参数是一个列表。所以atom_chars()从字符构造Atomics,而atom_codes()从ASCII序列构造Atomics。
例子
| ?- atom_chars(X, ['t','i','g','e','r']). X = tiger yes | ?- atom_chars(A, ['t','o','m']). A = tom yes | ?- atom_codes(X, [97,98,99,100,101]). X = abcde yes | ?- atom_codes(A, [97,98,99]). A = abc yes | ?-
分解Atomics
Atomics分解是指从一个Atomics中,我们可以得到一个字符序列,或者一个ASCII码序列。为此,我们必须使用相同的atom_chars() 和atom_codes() 谓词。但一个区别是,在这两种情况下,第一个参数将是一个Atomics,第二个参数将是一个变量。所以atom_chars()将Atomics分解为字符,而atom_codes()将Atomics分解为ASCII序列。
例子
| ?- atom_chars(tiger,X). X = [t,i,g,e,r] yes | ?- atom_chars(tom,A). A = [t,o,m] yes | ?- atom_codes(tiger,X). X = [116,105,103,101,114] yes | ?- atom_codes(tom,A). A = [116,111,109] (16 ms) yes | ?-
Prolog 中的咨询
咨询是一种技术,用于合并来自不同文件的谓词。我们可以使用 Consult() 谓词,并传递文件名来附加谓词。让我们看一个示例程序来理解这个概念。
假设我们有两个文件,即 prog1.pl 和 prog2.pl。
程序(prog1.pl)
likes(mary,cat). likes(joy,rabbit). likes(tim,duck).
程序(prog2.pl)
likes(suman,mouse). likes(angshu,deer).
输出
| ?- [prog1]. compiling D:/TP Prolog/Sample_Codes/prog1.pl for byte code... D:/TP Prolog/Sample_Codes/prog1.pl compiled, 2 lines read - 443 bytes written, 23 ms yes | ?- likes(joy,rabbit). yes | ?- likes(suman,mouse). no | ?- consult('prog2.pl'). compiling D:/TP Prolog/Sample_Codes/prog2.pl for byte code... D:/TP Prolog/Sample_Codes/prog2.pl compiled, 1 lines read - 366 bytes written, 20 ms warning: D:/TP Prolog/Sample_Codes/prog2.pl:1: redefining procedure likes/2 D:/TP Prolog/Sample_Codes/prog1.pl:1: previous definition yes | ?- likes(suman,mouse). yes | ?- likes(joy,rabbit). no | ?-
现在从这个输出我们可以了解到这并不像看起来那么简单。如果两个文件有完全不同的子句,那么它会正常工作。但是,如果存在相同的谓词,那么当我们尝试查阅该文件时,它将检查第二个文件中的谓词,当它找到某些匹配项时,它只是从本地数据库中删除相同谓词的所有条目,然后加载再次从第二个文件中获取它们。