处理 Pascal 文件时程序无法正常工作

procedures don't work properly when dealing with files in pascal

在这个程序中,当我尝试将代码块 [1] 和 [2] 放入过程中时,调用它们时它们无法正常工作,而当我将它们保留在主程序中时,只有第一个可以正常工作第二个没有,当我注释掉第一个时,第二个按预期工作......你能发现错误吗,我认为这是从用户那里获取文件名导致的,当我选择文件名时正常工作

program Linked_lists_files;
type
Node = ^T;
T = record
    num : integer;
    next : Node;
    End;
var
File1 : Text;
N, i, j, cmp, y, x, Num, matrixvalue : integer;
Head, Tail, Head2, Tail2, Head3, Tail3 : Node;
s : string;
matrix : array [1..20, 1..20] of Integer;

//  procedures

// [1]
Procedure fillFile();
Begin
write('Input file name to create : '); 
 readln(s);
 assign(File1,s);
 rewrite(File1);
 Repeat
 write('Enter a number : ');
 readln(N);
 if (N>=0) then
    writeln(File1, N);
 Until (N<0);
 close(File1);
End;

// [2]
Procedure GetFromFile();
Begin
cmp := 0;
 write('Enter file name to read from : '); 
 readln(s);
 assign(File1, s);
 reset(File1);
 while not eof(File1) Do
    Begin
        readln(File1, N);
        if (Head = Nil) then
        Begin
            new(Head);
            Tail := Head;
        End
        Else
        Begin
            new(Tail^.next);
            Tail := Tail^.next;
        End;
        Tail^.num := N;
        Tail^.next := Nil;
        cmp := cmp + 1;
    End;
Close(File1);
Write('Elements of the list : ');
Tail := Head;
if (Head<>nil) then
Begin
    while(Tail <> nil) Do
    Begin
        write('[',Tail^.num,']', ' ');
        Tail := Tail^.next;
    End;
End
Else
Writeln('[!] The list is empty');
writeln;
writeln('Number of elements in the list : ', cmp);
End;

// [3]
Procedure SaveFromFile();
Begin
Head :=  Nil;
write('Enter file name to read from : '); readln(s);
writeln('[+] Fill in your list');
Repeat
write('+ Enter an integer : ');
read(y);
if (y>=0) then
Begin
if (Head = Nil) then
Begin
    new(Head);
    Tail := Head;
End
Else
Begin
    new(Tail^.next);
    Tail := Tail^.next;
End;
Tail^.num := y;
Tail^.next := Nil;
End;
Until y<0;
assign(File1, s);
rewrite(File1);
Tail := Head;
while(Tail <> nil) Do
Begin
    Num := Tail^.num;
    Tail := Tail^.next;
    Writeln(File1, Num);
End;
Close(File1);
Writeln('[+] Elements of the lists have been successfully added to the new file');
End;

// [4]
Procedure SquareMatrix();
Begin
cmp := 0;
x := 0;
writeln('[+] Fill in your list');
Repeat
write('+ Enter an integer : ');
read(y);
if (y>=0) then
Begin
if (Head3 = Nil) then
Begin
    new(Head3);
    Tail3 := Head3;
End
Else
Begin
    new(Tail3^.next);
    Tail3 := Tail3^.next;
End;
Tail3^.num := y;
Tail3^.next := Nil;
cmp := cmp + 1;
End;
Until y<0;

while (cmp<>1) Do
Begin
    if (cmp mod 2 <> 0) and (cmp <> 1) then 
        x := x + 1;
    cmp := cmp div 2;
End;    
if (x>0) then
writeln('[-] False')
Else
writeln('[+]True');
End;

// [5]
Procedure ElementsOfSM();
Begin
cmp := 0;
x := 0;
writeln('[+] Fill in your list');
Repeat
write('+ Enter an integer : ');
read(y);
if (y>=0) then
Begin
if (Head = Nil) then
Begin
    new(Head);
    Tail := Head;
End
Else
Begin
    new(Tail^.next);
    Tail := Tail^.next;
End;
Tail^.num := y;
Tail^.next := Nil;
cmp := cmp + 1;
End;
Until y<0;
Tail := Head;
i := 1;
j := 1;
        while(Tail <> nil) Do
        Begin
            matrixvalue := Tail^.num;
            matrix[i,j] := matrixvalue;
            Tail := Tail^.next;
            j := j + 1;
            if (j = sqrt(cmp)+1) then
                Begin
                    i := i + 1;
                    j := 1;
                End;
            
        End;
for i:=1 to cmp Do
    for j:=1 to cmp Do
    Begin
        if (matrix[i,j]<>0) then
        writeln('[',matrix[i,j],']',' : ','[',i,',',j,']');
    End; 
End;

// [6]
Procedure Element();
Begin
write('Enter the number of the line : ');
read(i);
write('Enter the number of the column : ');
read(j);
write('The element corresponding to ','[',i,',',j,'] is : ','[',matrix[i,j],']');
writeln;
End;

// [7]
Procedure WriteP();
Begin
write('Enter the number of the line : ');
read(i);
write('Enter the number of the column : ');
read(j);
write('Enter the value you want to pass in : ');
read(N);
matrix[i,j] := N;
writeln('The new matrix');  
for i:=1 to cmp Do
    for j:=1 to cmp Do
    Begin
        if (matrix[i,j]<>0) then
        writeln('[',matrix[i,j],']',' : ','[',i,',',j,']');
    End; 
writeln;
End;

// [8]
Procedure Content();
Begin
write('Enter the number of the line : ');
read(i);
write('Enter the number of the column : ');
read(j);
writeln('The value stored inn this cell is : ','[', matrix[i,j],']');
End;

// Start of main program
Begin
 Head := Nil;
 Repeat
 writeln('*********** MENU ***********');
 writeln('[1] fillFile');
 writeln('[2] GetFromFile');
 writeln('[3] SaveFromFile');
 writeln('[4] SquareMatrix');
 writeln('[5] ElementsOfSM');
 writeln('[6] Element');
 writeln('[7] WriteP');
 writeln('[8] Content');
 writeln('*********** End ***********');
 write('Choose one : ');
 read(N);
 
 case N of
 1 : fillFile();
 
 2 : GetFromFile();
 
 3 : SaveFromFile();
 
 4 : SquareMatrix();
 
 5 : ElementsOfSM();
 
 6 : Element();
 
 7 : WriteP();
 
 8 : Content();
 End;
 
 Until (N<>1) and (N<>2) and (N<>3) and (N<>4) and (N<>5) and (N<>6) and (N<>7) and (N<>8) and (N<>9);

End.

您描述的问题是由 Read 语句的已知行为引起的;基本上,第二次(及后续)调用它时,它会立即 returns,无需等待任何键盘输入,也无需阅读任何内容。

发生这种情况是因为 FPC 与商业 Delphi 开发包中的 Object Pacal 密切相关,在 Delphi 的情况下,这是官方记录的行为。

来自Delphi (v7) 联机帮助:

Delphi syntax: Text files: procedure Read( [ var F: Text; ] V1 [, V2,...,Vn ] );

Description The Read procedure can be used in Delphi code in the following ways. [...] With a type string variable:

Read reads all characters up to, but not including, the next end-of-line marker or until Eof(F) becomes true; it does not skip to the next line after reading. If the resulting string is longer than the maximum length of the string variable, it is truncated. After the first Read, each subsequent Read sees the end-of-line marker and returns a zero-length string (emphasis added). Use multiple Readln calls to read successive string values.

幸运的是,解决方案很简单,使用 readln,而不是 read,如

readln(s);

更新 确保将 readall 个实例替换为 readln,因为您留下了正如@TomB运行berg 评论的那样,其中的数量没有变化。

之后,再次 运行 您的代码和 select 1 从菜单中,您会发现 fillFile 执行,但程序终止于 until ... 行。这是因为在整个程序中将同一个全局变量 N 用于多个不同的目的是一个 非常 的坏主意。因此,您应该进一步(仔细)编辑您的代码,以便它尽可能仅将全局变量用于全局目的。将 all 所有其他变量变成局部变量,最好使用与全局变量不同的名称。如果在那之后您仍然遇到问题,请提交一个新的问题。