Pascal中While循环检测EOF时无法退出的问题排查
Pascal读取文件时EOF识别失败问题解决
问题描述
需要读取input.txt中的字符序列,按规则转换后输出到salida.txt,但程序中的While循环无法正确识别EOF,导致无法正常退出,最终输出大量无效的@字符。
现有代码
program LaboratorioPascal; uses crt; var sec, sal: Textfile; v: char; por_especial, cont_palabra, cont_caracter, cont_especial: integer; vocales2: set of char; pares: set of char; impares: set of char; consonantes: set of char; consonantes2: set of char; procedure numeros(var x: char); begin case x of '0': Write(sal, '0'); '1': Write(sal, '1'); '2': Write(sal, '4'); '3': begin Write(sal, '2'); Write(sal, '7'); end; '4': Write(sal, '8'); '5': begin Write(sal, '1'); Write(sal, '2'); Write(sal, '5'); end; '6': begin Write(sal, '1'); Write(sal, '2'); end; '7': begin Write(sal, '3'); Write(sal, '4'); Write(sal, '3'); end; '8': begin Write(sal, '1'); Write(sal, '6'); end; '9': begin Write(sal, '7'); Write(sal, '2'); Write(sal, '9'); end; else Exit; end; end; function vocales(var s: char): char; begin case s of 'e': vocales := 'u'; 'a': vocales := 'o'; 'i': vocales := 'a'; 'o': vocales := 'e'; else vocales := 'i'; end; end; begin assign(sec, 'input.txt'); // Le asignamos un archivo del cual lea reset(sec); // arrancamos la secuencia read(sec, v); // leemos la secuencia. avz(sec, v) assign(sal, 'salida.txt'); rewrite(sal); vocales2 := ['a', 'e', 'i', 'o', 'u']; pares := ['0', '2', '4', '6', '8']; impares := ['1', '3', '5', '7', '9']; consonantes := ['b', 'c', 'd', 'f', 'g', 'h', 'j','k','l','m', 'n']; consonantes2 := ['p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z']; por_especial := 0; cont_palabra := 0; cont_caracter := 0; cont_especial := 0; writeln('El objetivo de este programa es cifrar un mensaje para favorecer a la inteligencia Rusa.'); while not eof(sec) do begin while v = ' ' do begin write(sal, ' '); read(sec, v); end; cont_palabra := cont_palabra + 1; while v <> ' ' do begin if (v in consonantes) or (v in consonantes2) then begin write(sal, '1'); end else begin if v in vocales2 then begin Write(sal, vocales(v)); end else begin if v in pares then; begin numeros(v); end; begin if v in impares then begin numeros(v); end else begin cont_especial := cont_especial + 1; Write(sal, '@'); end; end; end; end; read(sec, v); end; end; write(cont_palabra, ' se crifraon con [Exito]'); close(sec); close(sal); end.
当前输出(salida.txt)
1o1ao i1o 1u1 i1 1e1111ie 1iu 1u 1e1ae o i1o 11a11u1o@@@ 1a1@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
已尝试的操作
查阅EOF相关资料但未找到Pascal相关内容;尝试在循环内添加if eof then Exit;,但程序仅能读取一个字符,问题未解决。
问题根源
- 初始读取未做EOF检查:程序开头直接执行
read(sec, v),若input.txt为空会直接报错;且外层循环依赖eof(sec)判断,但内层循环在到达EOF后仍会继续处理v的旧值,导致无限写入@。 - 语法错误导致逻辑混乱:
if v in pares then;末尾多了分号,使得后续的numeros(v)调用无条件执行,同时后续的奇偶判断也会重复执行,逻辑冲突。 - 内层循环未处理EOF:在内层
while v <> ' '循环中,读取字符后未检查是否到达EOF,导致EOF后仍进入循环体处理无效字符。
修复方案
program LaboratorioPascal; uses crt; var sec, sal: Textfile; v: char; cont_palabra, cont_especial: integer; vocales2: set of char; pares: set of char; impares: set of char; consonantes: set of char; procedure numeros(x: char); begin case x of '0': Write(sal, '0'); '1': Write(sal, '1'); '2': Write(sal, '4'); '3': begin Write(sal, '2'); Write(sal, '7'); end; '4': Write(sal, '8'); '5': begin Write(sal, '1'); Write(sal, '2'); Write(sal, '5'); end; '6': begin Write(sal, '1'); Write(sal, '2'); end; '7': begin Write(sal, '3'); Write(sal, '4'); Write(sal, '3'); end; '8': begin Write(sal, '1'); Write(sal, '6'); end; '9': begin Write(sal, '7'); Write(sal, '2'); Write(sal, '9'); end; else Exit; end; end; function vocales(s: char): char; begin case s of 'e': vocales := 'u'; 'a': vocales := 'o'; 'i': vocales := 'a'; 'o': vocales := 'e'; 'u': vocales := 'i'; else vocales := 'i'; end; end; begin assign(sec, 'input.txt'); reset(sec); assign(sal, 'salida.txt'); rewrite(sal); vocales2 := ['a', 'e', 'i', 'o', 'u']; pares := ['0', '2', '4', '6', '8']; impares := ['1', '3', '5', '7', '9']; consonantes := ['b', 'c', 'd', 'f', 'g', 'h', 'j','k','l','m', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z']; cont_palabra := 0; cont_especial := 0; writeln('El objetivo de este programa es cifrar un mensaje para favorecer a la inteligencia Rusa.'); while not eof(sec) do begin read(sec, v); while not eof(sec) and (v = ' ') do begin write(sal, ' '); read(sec, v); end; if eof(sec) then break; cont_palabra := cont_palabra + 1; while not eof(sec) and (v <> ' ') do begin if v in consonantes then begin write(sal, '1'); end else if v in vocales2 then begin Write(sal, vocales(v)); end else if (v in pares) or (v in impares) then begin numeros(v); end else begin cont_especial := cont_especial + 1; Write(sal, '@'); end; if not eof(sec) then read(sec, v); end; end; writeln(cont_palabra, ' se cifraron con [Exito]'); close(sec); close(sal); end.
修复要点说明
- 调整读取逻辑:将初始读取移到外层循环内,每次循环先读取字符,再进行判断,避免初始读取空文件的问题。
- 添加EOF检查:所有内层循环和读取操作前都添加
not eof(sec)判断,确保到达EOF时及时退出循环。 - 修复语法错误:删除
if v in pares then;的多余分号,合并辅音集合简化判断,修正拼写错误crifraon为cifraron。 - 优化参数传递:
numeros和vocales函数无需使用var参数,因为仅读取字符值,不修改原变量。
内容的提问来源于stack exchange,提问作者Facundo Blanco
相关产品推荐
相关产品推荐

