Como funciona a read-line em Lisp ao chegar a eof?
fr.txt
com 3 colunas de texto nele:
65 A #\A
97 a #\a
192 À #\latin_capital_letter_a_with_grave
224 à #\latin_small_letter_a_with_grave
etc...
Eu quero criar uma função para ler a primeira coluna (e eventualmente a terceira também) e escrevê-la em outro arquivo de texto chamado alphabet_code.txt
.
até agora tenho esta função:
(defun alphabets()
(setq source (open "fr.txt" :direction :input :if-does-not-exist :error))
(setq code (open "alphabet_code.txt" :direction :output :if-does-not-exist :create :if-exists :supersede))
(loop
(setq ligne (read-line source nil nil))
(cond
((equal ligne nil) (return))
(t (print (read-from-string ligne) code))
)
)
(close code)
(close source)
)
Os meus problemas:
não entendo como funcionam os parâmetros da linha de leitura. Li este documento, mas ainda é muito obscuro para mim. Se alguém tivesse exemplos muito simples, isso ajudaria.
com o código atual, eu recebo este erro:
*** - read: input stream #<input string-input-stream> has reached its end
mesmo que eu mude onil nil
em(read-line source nil nil)
para outros valores.
1 answers
As suas perguntas
read-line
argumentos facultativos
read-line
aceita 3 argumentos opcionais:
-
eof-error-p
: o que fazer no EOF (por omissão: erro) -
eof-value
: o que retornar em vez do erro quando você ver EOF -
Estás a ligar-lhe do teu ...
print-object
método (esqueça isso por agora)
Por exemplo, quando o stream
está em EOF,
-
(read-line stream)
vai sinalizar oend-of-file
erro -
(read-line stream nil)
vai voltarnil
-
(read-line stream nil 42)
vai voltar42
.
Note que (read-line stream nil)
é o mesmo que (read-line stream nil nil)
mas as pessoas geralmente ainda passam o segundo argumento opcional explicitamente.
eof-value
de nil
está bem para read-line
porque nil
não é uma cadeia de caracteres e read-line
só devolve cadeias de caracteres.
Note também que, em caso de read
O segundo argumento opcional é, tradicionalmente, o próprio stream
: (read stream nil stream)
. É bastante conveniente.
Erro
Você está recebendo o erro de read-from-string
, Não read-line
, porque, aparentemente, tens uma linha vazia no teu ficheiro.
string-input-stream
, Não file-stream
.
O seu código
O seu código está correcto funcionalmente, mas muito errado estilisticamente.
-
with-open-file
Sempre que possível. - não deve utilizar
print
em código, é uma estranha função de legado, principalmente para uso interativo. - Você não pode criar variáveis locais com
setq
- utilizaçãolet
ou outras formas equivalentes (neste caso, você nunca precisarálet
! :-)
(defun alphabets (input-file output-file)
(with-open-stream (source input-file)
(with-open-stream (code output-file :direction :output :if-exists :supersede)
(loop for line = (read-line source nil nil)
as num = (parse-integer line :junk-allowed t)
while line do
(when num
(write num :stream code)
(write-char #\Newline code))))))
(alphabets "fr.txt" "alphabet_code.txt")
Ver os documentos:
Em alternativa, em vez de (when num ...)
Eu poderia ter usado o correspondente loop
condicional .
Também, em vez de write
+write-char
eu podia ter escrito.
Note que eu não passo os argumentos dewith-open-stream
que são idênticos aos valores por omissão.
Os valores por omissão são definidos em pedra, e quanto menos código você tem que escrever e seu usuário tem que ler, menos é a chance de erro.