Upload
others
View
3
Download
0
Embed Size (px)
Citation preview
Entrada e Saída
Prof. Elaine Faria e Hiran NonatoProgramação Lógica
UFU 2012
Créditos
• O material a seguir consiste de adaptações e extensões dos originais gentilmente cedidos pelo Prof. Alexsandro Santos Soares
Arquivos de Dados
• A comunicação com o Prolog até agora foi feita por meio de consultas realizadas pelo usuários que são respondidas através de instanciações de variáveis
• Muitas vezes essa forma de comunicação não é suficientemente adequada– Entrada de dados na forma de linguagem natural– Saída em um dado formato desejado– Entrada e saída para qualquer periférico do computador
Arquivos de Dados
• Existem predicados prédefinidos com o intuito de auxiliar na entrada/saída de dados– São dependentes da implementação da linguagem
Prolog usada
Arquivos de Dados
Luis, A. M. Palazzo, Introdução à Programação Prolog, Educat, 1997.
Arquivos de Dados
• Durante a execução de um programa Prolog dois arquivos estão ativos– um para entrada "fonte de entrada corrente"– um para saída "fonte de saída corrente “
• No início da execução essas duas fontes correspondem ao terminal do usuário
• A fonte de entrada corrente pode ser mudada a qualquer momento para um outro arquivo
see(novoArqEnt).
Arquivo de Entrada
• Exemplo do uso do see...see(arq1).le_do_arquivo(Informacao).see(user)....
Arquivos de Saída
• A fonte de saída corrente pode ser mudada – tell(novoArqSai).
• Exemplo do uso do tell...tell(arq3).grava_no_arquivo(Informacao).tell(user)....
Arquivos de Dados
• Dois outros predicados devem ser utilizados para fechar os arquivos correntes de entrada e saída respectivamente– seen/0 e told/0
Abertura de um arquivo
• Podese também abrir um fluxo (stream)
…open(‘arquivo.txt‘, write, Fluxo),...close(Fluxo),…
Abertura de um arquivo
• Para estender um arquivo existente, temos que abrir um fluxo em modo append
…open(‘arquivo.txt‘, append, Fluxo),....close(Fluxo),...
Arquivos de Dados• Os arquivos podem ser processados somente na forma sequencial
• A requisição para a leitura irá ocasionar a leitura a partir da posição corrente dessa fonte de entrada
• Após a leitura, a posição corrente da fonte de entrada será, o próximo item que ainda não foi lido
• Se uma requisição de leitura é feita para o fim do arquivo retorna a constante "end_of_file“
• Predicado predefinido at_end_of_stream(F) usado para verificar se o fim da stream foi atingido
Arquivos de Dados
• A saída de informações ocorre de maneira similar à entrada – A requisição de saída irá adicionar a informação
requisitada no final da fonte de saída corrente
Arquivos de Dados
• Há duas maneiras de se utilizar os arquivos em Prolog– Considerando o caractere como elemento básico do
arquivo– Considerando unidades maiores como elemento básico
do arquivo
Arquivos de Dados
• Usando o caractere como elemento básico arquivo– Predicados: get e put
• Usando unidades maiores como elemento básico do arquivo– As unidades são os termos Prolog: read e write
• O uso de cada uma dessas modalidades depende do contexto do problema
Processamento de Arquivos de Termos
• read– Usada para leitura de dados a partir da fonte corrente
read([A],X)leitura do próximo termo que irá unificar com XSe X é uma variável então X será instanciada com TSe a unificação não for possível então o objetivo read(X) irá falharCada termo deve ser seguido por um ponto e um espaço ou enterA representa o arquivo não é obrigatório
– É determinístico não ocorre backtracking
Processamento de Arquivos de Termos
• write– Fornece a saída de um termo para a fonte corrente
write([A], X)• tab
– O predicado tab(N) irá ocasionar a saída de N espaços • nl
– O predicado nl(sem argumentos) irá ocasionar o início de uma nova linha
Exemplo 1 Cubo
cubo :read(X), processa(X).
processa(fim) : !.processa(N) :
C is N*N*N,write(C),cubo.
?cubo.2.85.2512.1728fim.true
Exemplo 2 Cubocubo : write('Próximo valor: '), read(X), processa(X).
processa(fim) : !.processa(N) : C is N*N*N, write('O cubo de '), write(N), write('é '), write(C), nl, cubo.
Dependendo da implementação, uma requisição ("flush/0" para descarregamento dos buffers de I/O) pode ser necessária após o comando de escrita no prompt
Exemplo 3 – Escrevendo Lista
• Procedimento escreveLista(L)escreveLista([]).escreveLista([X | L]) :write(X), nl, escreveLista(L).
• Procedimento escreveLista2(L)escreveLista2([]).escreveLista2([L | LL]) :
imprime(L), nl, escreveLista2(LL).
imprime([]).imprime([X | L]) :
write(X), tab(1), imprime(L).
Exemplo 4
• Programa em Prolog que lê o arquivo (casas.txt) e o exibe na tela.
principal: open('casas.txt',read,F), read(F,C1), read(F,C2), read(F,C3), read(F,C4), close(F), write([C1,C2,C3,C4]), nl.
grifinoria.lufa_lufa.corvinal.sonserina.
casas.txt:
Exemplo 5principal: open('casas.txt',read,F), leiaCasas(F,Casas), close(F), write(Casas), nl.
leiaCasas(F,[]): at_end_of_stream(F).
leiaCasas(F,[X|L]): \+ at_end_of_stream(F), read(F,X), leiaCasas(F, L).
Exemplo 5 com cortes verdesprincipal: open('casas.txt',read,F), leiaCasas(F,Casas), close(F), write(Casas), nl.
leiaCasas(F,[]): at_end_of_stream(F), !.
leiaCasas(F,[X|L]): \+ at_end_of_stream(F), !, read(F,X), leiaCasas(F, L).
Exemplo 6
• Problema– Arquivo denominado arq1 contendo termos na forma
item(Nro, Descrição, Preço, Fornecedor)
– Desejase produzir um outro arquivo que contenha somente os itens fornecidos por um determinado fornecedor
– O nome do fornecedor deve ser escrito no início do arquivo
Exemplo – cont.principal(NomeForn): open('C:\\Entrada.txt',read,AEnt), open('C:\\Saida.txt',write,ASaida), write(ASaida, NomeForn), write(ASaida, '\n'), leiaForn(AEnt,ASaida, NomeForn), close(AEnt), close(ASaida).
leiaForn(AEnt,_,_): at_end_of_stream(AEnt), !.
leiaForn(AEnt,ASaida,NomeForn): read(AEnt,item(Nro,D,P,NomeForn)),!, write(ASaida, item(Nro,D,P)), write(ASaida,'\n'), leiaForn(AEnt,ASaida,NomeForn).
leiaForn(AEnt,ASaida,NomeForn): leiaForn(AEnt,ASaida,NomeForn).
Processamento de caracteres
• Um caractere é escrito na fonte de saída corrente por meio do objetivo
put(C)C é o código ASCII (um número entre 0 e 255) do caractere a ser escrito
– Exemplo?put(65), put(66), put(67).produz a saída:ABC
Processamento de caracteres
• Um caractere pode ser lido a partir da fonte de entrada corrente por meio do objetivo
get0(C)ocasiona a leitura do caractere corrente e torna a variável C instanciada com o código ASCII do caractere
Processamento de caracteres
• Leitura de caracteres imprimíveis saltando sobre todos os caracteres nãoimprimíveis (espaços em branco)
get(C)
Processamento de caracteres
• O predicado get_code/2 lê o próximo caracter disponível de um fluxo– Primeiro argumento: um fluxo– Segundo argumento: o código do caracter
Exemplo usando get_codeleiaPalavra(Fluxo,Palavra): get_code(Fluxo,Caracter), verificaELeiaResto(Caracter,Caracteres,Fluxo), atom_codes(Palavra,Caracteres).
verificaELeiaResto(10, [], _): !.verificaELeiaResto(32, [], _): !.verificaELeiaResto(1, [], _): !. verificaELeiaResto(Caracter,[Caracter|Caracteres],F): get_code(F,ProxCaracter), verificaELeiaResto(ProxCaracter,Caracteres,F).
Conversão de Termos
• Predicado prédefinido atom_codes/2, que relaciona os átomos com o seu código ASCII. – atom_codes(X, L) é verdadeiro, se L é a lista dos
códigos dos caracteres em A– Exemplo
atom_codes(zx232, [122, 120, 50, 51, 50])
Dividindo programas em arquivos
• Muitos predicados Prolog fazem uso dos mesmos predicados básicos– Por exemplo: member/2, append/3
• É claro que você não quer redefinilos a cada vez que necessitar deles– Prolog oferece muitos modos de fazer isto
Leitura de programas
• A forma mais simples de dizer ao Prolog para ler as definições de predicados armazenadas em um arquivo é usar os colchetes
? [meuArq].{consulting(meuArq.pl)…}{meuArq.pl consulted, 233 bytes}true?
Leitura de programas
• Você também pode consultar mais de um arquivo por vez
? [meuArq1, meuArq2, meuArq3].{consulting meuArq1.pl…}{consulting meuArq2.pl…}{consulting meuArq3.pl…}
Leitura de programas
• Você não precisa fazer isto interativamente • Ao invés disto, você pode usar uma diretiva na base de
dados
: [meuArq1, meuArq2].
Leitura de programas
• Talvez, muitos arquivos, independentemente, consultem o mesmo arquivo.
• Verificação extra se as definições dos predicados já são conhecidas: ensure_loaded/1
: ensure_loaded([meuArq1, meuArq2]).
Módulos
• Imagine que você está escrevendo um programa que gerencie um banco de dados sobre filmes
• Você projetou dois predicados:– imprimeAtores/1– imprimeFilmes/1
• Eles estão armazenados em arquivos diferentes• Ambos usam um predicado auxiliar:
– exibeLista/1
O arquivo principal .pl
% Arquivo principal.pl
: [imprimeAtores].: [imprimeFilmes].
O arquivo principal .pl
% Arquivo principal.pl
: [imprimeAtores].: [imprimeFilmes].
? [principal].
O arquivo principal .pl
% Arquivo principal.pl
: [imprimeAtores].: [imprimeFilmes].
? [principal].{consulting principal.pl}
O arquivo principal .pl
% Arquivo principal.pl
: [imprimeAtores].: [imprimeFilmes].
? [principal].{consulting principal.pl}{consulting imprimeAtores.pl}
O arquivo principal .pl
% Arquivo principal.pl
: [imprimeAtores].: [imprimeFilmes].
? [principal].{consulting principal.pl}{consulting imprimeAtores.pl}{imprimeAtores.pl consulted}
O arquivo principal .pl
% Arquivo principal.pl
: [imprimeAtores].: [imprimeFilmes].
? [principal].{consulting principal.pl}{consulting imprimeAtores.pl}{imprimeAtores.pl consulted}{consulting imprimeFilmes.pl}
O arquivo principal .pl
% Arquivo principal.pl
: [imprimeAtores].: [imprimeFilmes].
? [principal].{consulting principal.pl}{consulting imprimeAtores.pl}{imprimeAtores.pl consulted}{consulting imprimeFilmes.pl}The procedure exibeLista/1 is being
redefined. Old file: imprimeAtores.plNew file: imprimeFilmes.plDo you really want to redefine it?(y, n, p, or ?)
Usando módulos• Predicado préconstruído module:
– module/1 e module/2– Para criar um módulo/biblioteca
• Predicado préconstruído use_module: – use_module/1 e use_module/2– Para importar predicados de uma biblioteca
• Argumentos– O primeiro argumento é o nome do módulo– O segundo e opcional argumento é uma lista dos predicados
exportados
Nota sobre módulos em Prolog
• Nem todos os interpretadores Prolog possuem este sistema de módulos
• SWI Prolog e Sicstus possuem
• O sistema de módulos do Prolog ainda não é compatível com a norma ISO
O módulo imprimeAtores.pl% Este é o arquivo: imprimeAtores.pl: module(imprimeAtores,[imprimeAtores/1]).
imprimeAtores(Filme): filmesAtor(Ator, Lista), exibeLista(Lista).
exibeLista([]): nl.exibeLista([X|L]): write(X), tab(1), exibeLista(L).
O módulo imprimeFilmes.pl% Este é o arquivo: imprimeFilmes.pl: module(imprimeFilmes,[imprimeFilmes/1]).
imprimeFilmes(Diretor): diretoresFilme(Filme, Lista), exibeLista(Lista).
exibeLista([]): nl.exibeLista([X|L]): write(X), nl, exibeLista(L).
O arquivo revisado principal.pl• % Este é o arquivo revisado principal.pl
: use_module(imprimeAtores).: use_module(imprimeFilmes).
% Este é o arquivo revisado principal.pl
: use_module(imprimeAtores,[imprimeAtores/1]).: use_module(imprimeFilmes,[imprimeFilmes/1]).
Bibliotecas
• Muitos dos predicados mais comuns já vem préconstruídos nos interpretadores Prolog
• Por exemplo, em SWI Prolog, member/2 e append/3 vem como parte de uma biblioteca
• Uma biblioteca é um módulo que define predicados comuns e pode ser carregada usando os predicados normais para importar módulos
Importando bibliotecas
• Ao especificar o nome de uma biblioteca que você quer usar, você pode informar que este módulo é uma biblioteca
• Prolog procurará no lugar certo, ou seja, em um diretório onde todas as bibliotecas estão guardadas
: use_module(library(lists)).
Referências
• Luis, A. M. Palazzo, Introdução à Programação Prolog, Educat, 1997.