Métodos de Programação I (2005/2006)
1
Ficheiro (file)
• O tipo estruturado file representa, em Pascal, uma estrutura
de dados capaz de armazenar dados ou resultados de
qualquer outro tipo
• É uma estrutura externa e, em geral, uma estrutura
permanente
• Permite a comunicação com o utilizador ou entre programas
• Estruturalmente é semelhante a uma tabela (array)
• Tamanho dinâmico
• Acesso sequencial
Diagrama sintático para o tipo file:
→
file of
→
tipo
→
Ficheiros standard:
Ficheiros com caracterı́sticas especiais, pré-declarados no sistema
◦ input: habitualmente especifica o terminal (stdin);
◦ output: habitualmente especifica o monitor (stdout);
Existem sistemas onde é possı́vel redeclarar estes ficheiros,
evitando assim a associação obrigatória ao terminal ou monitor.
Métodos de Programação I (2005/2006)
2
O Pascal permite usar o nome (identificador) de qualquer ficheiro
no cabeçalho do programa, indicando assim ao sistema operativo
que este programa vai usar estes ficheiros:
program Ex_ficheiros(input, dados, resultados, output);
• Os ficheiros podem existir previamente ou podem ser criados
aquando da execução do programa.
• Um ficheiro (não–standard) é uma variável logo tem de ser
declarado num cabeçalho.
var
entrada: file of integer;
resultados: file of char;
(mais) Exemplos:
type
FichInt = file of integer;
var
entrada: FichInt;
resultados:
ERRO:
text;
ficheiros:
⇐⇒
file of char;
file of file of real;
Não existem ficheiros de ficheiros!
Métodos de Programação I (2005/2006)
• Os ficheiros input e output são do tipo text
• A instrução assign liga a variável do tipo ficheiro ao seu nome
externo: por exemplo, assign(entrada,"dados"); diz ao S.O.
que o identificador de ficheiro de inteiros entrada (declarado no
acetato anterior) fica associado ao ficheiro externo de
nomedados (que tem de ser do mesmo tipo, ou seja, um ficheiro
só com números inteiros).
• É sempre necessário preparar o ficheiro para leitura ou para
escrita:
◦ reset: a instrução reset(fich), onde fich é um
identificador de uma variável do tipo ficheiro, coloca o
ficheiro de nome fich no modo de leitura ou entrada
(Pode ser inspeccionada (lida) mas não pode ser
alterada.)
◦ rewrite: a instrução rewrite(fich), onde fich é um
identificador de uma variável do tipo ficheiro, coloca o
ficheiro de nome fich no modo de escrita ou saı́da
(Pode ser alterada mas não pode ser inspeccionada)
3
Métodos de Programação I (2005/2006)
4
Estrutura e acessos a ficheiros:
• Um ficheiro é uma sequência de elementos (componentes) do
mesmo tipo (a noção de linhas só existe nos ficheiros de texto)
• Cada componente é uma identidade indivisı́vel:
var
Fstring10: file of array[1..10] of char;
– Cada componente é uma tabela de 10 elementos do tipo
caracter;
– Não é possı́vel aceder a um caracter individual;
• Conceptualmente, um ficheiro é uma tabela de elementos
seguidos do mesmo tipo com acesso sequencial:
var f: file of integer
-45
-11
-4
0
1
7
18 27 35 40
↑
18
variável tampão (buffer)
43
50
/
eof
• Quando da declaração da variável ficheiro, é–lhe associada uma
variável especial, dita variável janela ou tampão (buffer), que
é do mesmo tipo dos elementos do ficheiro.
• A variável janela permite o acesso sequencial a cada componente
do ficheiro (da primeira para a última), ficando com uma cópia
do valor da componente actualmente apontada pela janela:
fˆ = 18
Métodos de Programação I (2005/2006)
5
Preparar o ficheiro para o modo de leitura:
reset(f ) – coloca a janela na primeira componente do ficheiro f,
atribui à variável fˆ uma cópia do valor desse elemento e, caso o
ficheiro seja não vazio, atribui o valor false à função lógica eof(f )
get(f ) – avança a janela para a próxima componente do ficheiro f,
modifica o valor da variável fˆ para a cópia do valor deste
elemento; caso o ficheiro tenha chegado ao fim, atribui o valor
true à função lógica eof(f )
Exemplo:
var f: file of integer;
num: integer;
. . .
reset(f);
-45
↑
-11
-45
fˆ
-4
0
1
7
18
27
35
40
43
50
/
eof
18
27
35
40
43
50
/
eof
eof(f ) = false
num:=f^; get(f);
-45
-11
↑
-11
fˆ
get(f);
-4
0
1
7
num= -45
eof(f ) = false
Métodos de Programação I (2005/2006)
-45
-11
-4
↑
0
-4
fˆ
1
7
6
18
num= -45
27
35
40
43
50
/
eof
50
/
↑
eof(f ) = false
. . .
get(f);
-45
-11
-4
0
1
7
18
27
35
40
43
?
eof(f ) = true
fˆ
get(f);
Error:
attempt to read past end of file
Problema: Carregar num vector de inteiros a informação contida
num ficheiro de inteiros:
reset(f);
n := 0;
while not eof(f) do
begin
n := n+1;
v[n] := f^;
get(f);
end;
Métodos de Programação I (2005/2006)
7
Preparar o ficheiro para o modo de escrita:
rewrite(f ) – (ficheiro f considera-se vazio) coloca a janela no “fim”
do ficheiro f; a variável fˆ está indefinida; atribui o valor true à
função lógica eof(f )
put(f ) – coloca o valor actual de fˆ como componente no ficheiro f;
avança a janela e a variável fˆ fica indefinida; atribui o valor
true à função lógica eof(f ).
Exemplo:
var f: file of char;
num: integer;
. . .
rewrite(f);
/
↑
?
fˆ
eof(f ) = true
f^:=’e’; put(f);
e
/
↑
?
fˆ
eof(f ) = true
Métodos de Programação I (2005/2006)
f^:=’x’; put(f);
f^:=’p’; put(f);
e
x
e
m
8
f^:=’e’; put(f);
f^:=’l’; put(f);
p
l
o
f^:=’m’; put(f);
f^:=’o’; put(f);
/
↑
?
fˆ
eof(f ) = true
Notas:
• Um mesmo ficheiro não pode ser utilizado para escrever e ler
simultaneamente
• É possı́vel usar o mesmo ficheiro para ler e escrever desde que
não seja problemático perder a informação anterior
• É possı́vel abrir o mesmo ficheiro várias vezes para leitura ou
para escrita
• Para actualizar um ficheiro existente é necessário criar um
novo ficheiro (ver próximo acetato)
• As funções read e write são mais simples de utilizar mas a
janela (buffer) permite ver (aceder) a componente que está
actualmente na janela sem de facto a ler (i.e., sem avançar a
janela para a próxima componente)
Métodos de Programação I (2005/2006)
9
Problema: Actualizar um ficheiro do tipo real com mais n valores
do mesmo tipo, contidos num dado vector.
var i : integer;
...
reset(f);
{ prepara f para leitura }
rewrite(res); { prepara res para escrita }
while not eof(f) do
begin
{ copia f para res }
res^ := f^;
put(res);
get(f);
{ proximo elemento de f }
end;
for i:=1 to n do
begin
{ coloca novos valores em res }
res^ := v[i];
put(res);
end;
...
Métodos de Programação I (2005/2006)
10
Ficheiros Formatados do tipo text
• Ficheiros do tipo caracter (text ⇐⇒ file of char)
• Facilitam a comunicação com utilizadores
• Fáceis de manipular
• Ineficientes
Sendo ficheiros onde cada componente é um caracter, é ainda
possı́vel ler e escrever números reais ou inteiros:
var
fich: text;
x: real;
num: integer;
c: char;
. . .
read(fich, c);
• lê o caracter actual de fich para c
write(fich, c);
• escreve o valor de c (um caracter) no final de fich
read(fich, num);
◦ avança espaços em branco
◦ lê a próxima sequência de caracteres até que fichˆ 6∈ {0 00 , . . . ,0 90 }
◦ converte no respectivo inteiro
Se a componente (caracter) actual da janela 6∈ {0 +0 ,0 −0 ,0 00 , . . . ,0 90 }
ocorre um erro
Métodos de Programação I (2005/2006)
11
write(fich, num);
◦ converte o número na respectiva string de dı́gitos
◦ escreve a string no ficheiro
◦ avança a janela
• Num ficheiro de texto existe um sı́mbolo especial, o caracter
newline que permite usar a instrução writeln():
writeln(fich, ’exemplo’);
m
write(fich, ’exemplo’);
write(fich, ’\n’);
• Num ficheiro de texto existe uma outra função lógica eoln() que
tem o valor true se a janela apontar um caracter newline e false
caso contrário
p
p
o
o
r \n c á \n /
↑
r
fˆ
eoln(f ) = false
r
\n
↑
fˆ
c
á
\n
eof(f ) = false
/
eoln(f ) = true
eof(f ) = false
Métodos de Programação I (2005/2006)
p
p
o
o
r
r
\n
\n
12
c á \n /
↑
c
fˆ
eoln(f ) = false
c
á
\n
↑
eof(f ) = false
/
eoln(f ) = true fˆ eof(f ) = false
p
o
r
\n
c
á
\n
/
↑
?
eoln(f ) = ? fˆ eof(f ) = true
• O Pascal standard acaba todos os ficheiros de texto com um
newline
• Também o readln() só pode ser usado em ficheiros de texto:
readln(fich,car);
◦ copia o valor de fich^ para car
◦ avança até ao encontrar o próximo ’\n’
◦ coloca a janela a apontar o caracter seguinte
Métodos de Programação I (2005/2006)
13
Considere o seguinte exemplo:
...
\n
3
4
1
\n
6
7
\n
/
var sum, n: integer;
...
reset(f);
sum := 0;
while not eof(f) do
begin
read(f, n);
sum := sum + n;
end;
...
Error:
attempt to read past end of file
• A instrução read(f, n) avança caracteres “brancos”, à procura
de um número inteiro e ’\n’ é um caracter “branco”!
Neste caso é conveniente usar um procedimento especializado que
ajuda a preparar o próximo input: um procedimento que ”salte
brancos” e deixe a janela a apontar o próximo caracter “não branco”
Métodos de Programação I (2005/2006)
14
Que acontecerá na situação seguinte?
...
\n
3
4
\n
T
7
\n
/
Para ler reais e inteiros de ficheiros de texto deverão criar-se
procedimentos para validar as entradas e fazer tratamento de
erros !
• Funções read e write com múltiplos argumentos
nos ficheiros de texto é possı́vel usar mais do que um argumento
na mesma chamada:



 read(fich,x1);
read(fich,x1, x2, x3); ⇐⇒
read(fich,x2);



read(fich,x3);

 read(fich,x1, x2, x3);
readln(fich,x1, x2, x3); ⇐⇒
 readln(fich);
Nota: quando as funções são chamadas sem argumentos do tipo
ficheiro, são usados, por defeito, os ficheiros standard
Métodos de Programação I (2005/2006)
15
Problema: Dado um texto, determinar a percentagem de
frequência de cada uma das letras desse texto.
Estratégia: Sendo,
◦ n o número total de letras que aparece no texto dado
◦ nx o número de vezes que aparece a letra x nesse texto
então, a frequência da letra x em percentagem é dada por,
f req(x) =
nx
× 100
n
Dado um ficheiro de texto, ler todos os seus caracteres e, para cada
um deles, caso seja letra do alfabeto, contar mais uma letra destas e
contar mais uma letra no total. Para cada uma das diferentes letras
encontradas, calcular a respectiva frequência.
Algoritmo genérico:
• Abrir fich, ficheiro de texto, para leitura;
• Enquanto fich for não vazio:
– ler caracter;
– caso caracter seja letra do alfabeto:
∗ incrementar contador respectivo
∗ incrementar contador total de letras
• Calcular, para cada letra encontrada, a respectiva frequência e
escrever no ficheiro de saı́da.
Métodos de Programação I (2005/2006)
Notas:
◦ Não se deve diferenciar entre maiúsculas e minúsculas
◦ Atenção às mudanças de linha!
• Uma vez que se terá que usar um contador para cada letra
possı́vel do alfabeto, considerar-se-á uma tabela de contadores,
ou seja,
array[’a’..’z’] of IntNNeg
• Serão, também, usados conjuntos do tipo letra para distinguir
entre caracteres letra e outros caracteres que possam aparecer
no texto
program Frequencia(texto,tabela,output);
type
IntNNeg = 0..32000;
Contador = array[’a’..’z’] of IntNNeg;
var
texto, tabela: text;
conta: Contador;
total, xminusc: IntNNeg;
{xminusc "transforma" Maiuscs em minuscs}
car: char;
16
Métodos de Programação I (2005/2006)
begin { programa principal }
{ inicia contadores conta }
for car:= ’a’ to ’z’ do conta[car]:=0;
{ le e conta totais }
assign(texto, ’texto.txt’);
reset(texto); { abre ficheiro modo leitura }
n := 0;
xminusc := ord(’a’)-ord(’A’);
{ leitura e contabilizacao }
while not eof(texto) do
begin
while not eoln(texto) do { "saltar" newline }
begin
read(texto, car);
if car in [’a’..’z’,’A’..’Z’]
then begin
if car in [’A’..’Z’]
then car := chr(ord(car)+xminusc);
conta[car] := conta[car]+1; { + esta letra }
total := total+1;
{ + uma letra }
end {if }
end; { while not eoln }
readln(texto); { avanca para prox. car. <> eoln }
end; { while not eof }
close(texto);
{ prepara ficheiro para escrita }
assign(tabela, ’tab.txt’);
rewrite(tabela);
{ calcula frequencia e escreve }
writeln(tabela,’***** Tabela de Frequencias *****’);
17
Métodos de Programação I (2005/2006)
writeln(tabela);
for car := ’a’ to ’z’ do
begin
write(tabela,’ ’, car:4,’:’);
writeln(conta[car]/total*100:5:2,’%’);
end;
close(tabela);
end.
18
Métodos de Programação I (2005/2006)
Aplicação deste programa sobre o próprio texto do programa
(ficheiro .p):
***** Tabela de Frequencias *****
a:13.28%
b: 1.99%
c: 6.77%
d: 2.79%
e:10.89%
f: 2.52%
g: 1.59%
h: 1.46%
i: 6.51%
j: 0.00%
k: 0.00%
l: 4.52%
m: 1.46%
n: 8.76%
o: 7.44%
p: 1.59%
q: 0.40%
r: 9.43%
s: 1.99%
t: 9.56%
u: 2.39%
v: 0.93%
w: 1.06%
x: 1.46%
y: 0.27%
z: 0.93%
19
Download

Acetatos sobre o tipo Ficheiro em Pascal