Pascal 错误使用';char'的文件;

Pascal 错误使用';char'的文件;,pascal,Pascal,我对这个代码有问题,我有两个char文件,一个是关于书籍的信息,另一个是空的,我必须在SAL中写一些来自S的信息,然后显示有多少本书与代码的前两位匹配,有多少是R,有多少是T。这个代码确实将信息表S写入SAL,但当它应该显示总数时,屏幕上会显示100。我读到它,它说这是“磁盘读取错误”的问题,*如果您“种子”键入的文件的不存在记录并尝试读取/写入它,通常会发生此错误。*,我真的不懂 我一直想弄明白,但一直没能弄明白。我注意到,如果我不写“whilenoteof(S)DO”,错误不会出现,但我当然

我对这个代码有问题,我有两个char文件,一个是关于书籍的信息,另一个是空的,我必须在SAL中写一些来自S的信息,然后显示有多少本书与代码的前两位匹配,有多少是R,有多少是T。这个代码确实将信息表S写入SAL,但当它应该显示总数时,屏幕上会显示100。我读到它,它说这是“磁盘读取错误”的问题,*如果您“种子”键入的文件的不存在记录并尝试读取/写入它,通常会发生此错误。*,我真的不懂

我一直想弄明白,但一直没能弄明白。我注意到,如果我不写“whilenoteof(S)DO”,错误不会出现,但我当然需要时间,如果有人能指出我的错误,我会非常感激

代码如下:

uses crt;

var 
i : byte;
s,sal: file of char;
v,l1,l2: char;
cs,cn,cl: integer;

pn,ps,tot: integer;

BEGIN
 cs:=0; cn:=0;  i:=0; cl:=0;
Assign (s, 'C:\Users\te\Documents\s.txt');
     {$I-}
     Reset (s);
     {$I+}
     if IOResult <> 0 then
     begin
       writeln('Error');
       halt(2);  
     end;

      Assign (sal, 'C:\Users\te\Documents\sal.txt');
     {$I-}
     Rewrite (sal);
     IOResult;
     {$I+}
     if IOResult <> 0 then
       halt(2);  


    writeln('Please write the code of the book, only 2 digits');
    read(L1);read(L2);
    read(s,v);

    while (not eof(s)) do
    begin

      for i:=1 to 2 do
      read(s,v);

      if (v = '0') then
      begin
      read(s,v);
        if (v = '1') or (v = '2') then
        begin

        for i:=1 to 5 do
        read(s,v);

        if (v = 'R') then
        begin
        read(s,v);
        cs:= cs + 1;
        end
        else
        begin

        if (v = 'T') then
        begin
        cn:= cn + 1;
        read(s,v);
        end;
      end;

      while (v <> '-') do
      read(s,v);
      while (v = '-') do
      read(s,v);

      if (v = L1) then
      begin
      write(sal, v);
      read(s,v);
       if (v = L2)  then
       begin
       write(sal,v);
       read(s,v);
       cl:= cl + 1;
       end;
      end;

      while ( v <> '/') do
      begin
      write(sal,v);
      read(s,v);
      end;
      write(sal, '-');
      end

      else
      begin
      for i:= 1 to 5 do
      read(s,v);

      if (v = 'R') then
      cs:= cs + 1
      else
      cn:= cn + 1;

      if (v = L1) then
      read(s,v);
      if (v = L2) then
      begin
      cl:= cl + 1;
      read(s,v);
     end;
    end;

     end


     else
     begin
     for i:= 1 to 5 do
     read(s,v);

     if (v = 'R') then
     cs:= cs + 1
     else
     cn:= cn + 1;

     if (v = L1) then
     read(s,v);
     if (v = L2) then
     begin
     cl:= cl + 1;
     read(s,v);
     end;
    end;
    end;



    tot:= cs + cn;
    ps:= (cs * 100) div tot;
    pn:= (cn * 100) div tot;



    writeln('TOTAL ',cl);
    writeln();
    writeln(ps,'% and',pn,'%');
我真的只需要别人对这段代码的看法,我想可能算法有缺陷。 谢谢

(编辑后,我看到您的代码现在在FPC中编译了w/o错误,所以我很高兴您能够自己修复错误)

由于这显然是一门课程,我不会为你修改你的代码,无论如何,即使如此,我恐怕你这样做是完全错误的

基本上,代码的主要错误在于,您试图控制在逐个字符读取源文件时发生的情况。坦率地说,这是一种绝望的尝试方式,因为它使执行流程变得不必要的复杂,并且充斥着if、but和循环。它还要求您在任何给定的步骤中保持对您正在尝试执行的操作的心理跟踪,并且生成的代码本质上是而不是自我记录-想象一下,如果您在六个月后回到您的代码,您能一眼就知道它是如何工作的吗?我个人当然不能

你需要以另一种方式分解任务。不要自下而上地分析问题(“如果我接下来读这个字符,那么我接下来需要做的是…”),而是自上而下地进行分析:尽管您的输入文件是一个字符
文件,但它包含一系列字符串,由
/
字符分隔,最后由
$
字符终止(但这个终止符并不重要)。所以你需要做的是一个接一个地读取这些字符串;一旦你找到了一个,检查它是否是你要找的字符串:如果是。按你需要的方式处理它,否则读取下一个字符串,直到文件结束

一旦你成功地阅读了一本书中的字符串,你就可以将它拆分成它所包含的各个字段。进行拆分最有用的函数可能是
Copy
,它可以让你从字符串中提取子字符串-在FPC帮助中查找。我已经包含了函数
ExtractTitle
EXTractPremission
它向您展示了编写类似函数以提取T/R代码和连字符后面的数字代码所需的操作。顺便说一句,如果您将来需要询问类似的q,如果您在文件中包含布局描述和各个字段的含义,这将非常有用

因此,我要向您展示的是如何通过逐个字符构建来读取
S.Txt
中的字符串序列。在下面的代码中,我使用一个函数
GetNextBook
,我希望这是一个合理的自解释函数。该代码在
中使用此函数,而
循环填充
BookRecord
字符串变量。然后,它只需将
BookRecord
写入控制台。当然,您的代码应该做的是处理
BookRecord
内容,查看它是否是您要查找的内容,然后再执行任务的剩余部分是否是

我希望你会同意,下面的代码比你q中的代码更清晰,更短,将来更容易扩展。用这种方式构造程序的关键是将程序的任务分解为一系列函数和过程,每个函数和过程执行一个子任务。用这种方式编写程序会更容易o“重新连接”程序以更改其功能,而无需重写函数/过程的内部

program fileofcharproject;

uses crt;

const
  sContents = '02022013Rto kill a mockingbird-1301/02012014Tpeter pan-1001/02032013Thowto-2301/02012012Tmaze runner-1001/02012012Tmaze runner-1001/02012012Tmaze runner-1001/$';
  InputFileName = 'C:\Users\MA\Documents\S.Txt';
  OutputFileName = 'C:\Users\MA\Documents\Sal.Txt';

type
  CharFile = File of Char; //  this is to permit a file of char to be used
                           //  as a parameter to a function/procedure

function GetNextBook(var S : CharFile) : String;
var
  InputChar : Char;
begin
  Result := '';

  InputChar := Chr(0);
  while not Eof(S) do begin
    Read(S, InputChar);
    // next, check that the char we've read is not a '/'
    //  if it is a '/' then exit this while loop
    if (InputChar <> '/') then
      Result := Result + InputChar
    else
      Break;
  end;
end;

function ExtractBookTitle(BookRecord : String) : String;
var
  p : Integer;
begin
  Result := Copy(BookRecord, 10, Length(BookRecord));
  p := Pos('-', Result);
  if p > 0 then
      Result := Copy(Result, 1, p - 1);
end;

procedure AddToOutputFile(var OutputFile : CharFile; BookRecord : String);
var
  i : Integer;
begin
  for i := 1 to Length(BookRecord) do
    write(OutputFile, BookRecord[i]);
  write(OutputFile, '/');
end;

function ExtractPreamble(BookRecord : String) : String;
begin
  Result := Copy(BookRecord, 1, 8);
end;

function TitleMatches(PartialTitle, BookRecord : String) : Boolean;
begin
  Result := Pos(PartialTitle, ExtractBookTitle(BookRecord)) > 0;
end;

var
  i : Integer; //byte;
  s,sal: file of char;
  l1,l2: char;
  InputChar : Char;
  BookFound : Boolean;
  cs,cn,cl: integer;
  pn,ps,tot: integer;
  Contents : String;
  BookRecord : String;
  PartialTitle : String;
begin
  //  First, create S.Txt so we don't have to make any assumptions about
  //  its contents

  Contents := sContents;
  Assign(s, InputFileName);
  Rewrite(s);

  for i := 1 to Length(Contents) do begin
    write(s, Contents[i]);  // writes the i'th character of Contents to the file
  end;

  Close(s);

  cs:=0; cn:=0;  i:=0; cl:=0;

  //  Open the input file
  Assign (s, InputFileName);
  {$I-}
  Reset (s);
  {$I+}
  if IOResult <> 0 then
  begin
    writeln('Error');
    halt(2);
  end;

  //  Open the output file
  Assign (sal, OutputFileName);
  {$I-}
  Rewrite (sal);
  IOResult;
  {$I+}
  if IOResult <> 0 then
   halt(2);

  //  the following reads the BookRecords one-by-one and copies
  //  any of them which match the partial title to sal.txt

  writeln('Enter part of a book title, followed by [Enter]');
  readln(PartialTitle);
  while not Eof(s) do begin
    BookRecord := GetNextBook(S);
    writeln(BookRecord);
    writeln('Preamble : ', ExtractPreamble(BookRecord));
    writeln('Title : ', ExtractBookTitle(BookRecord));
    if TitleMatches(PartialTitle, BookRecord) then
      AddToOutputFile(sal, BookRecord);
  end;

  //  add file '$' to sal.txt
  write(sal, '$');

  Close(sal);
  Close(s);

  writeln('Done, press any key');
  readln;

end.
项目的程序文件;
使用阴极射线管;
常数
sContents='0202013RTO杀死一只知更鸟-1301/020201014彼得·潘-1001/02032013指南-2301/020012012TMAze runner-1001/020012012TMAze runner-1001/020012012TMAze runner-1001/$';
InputFileName='C:\Users\MA\Documents\S.Txt';
OutputFileName='C:\Users\MA\Documents\Sal.Txt';
类型
CharFile=File of Char;//允许使用Char文件
//作为函数/过程的参数
函数GetNextBook(var S:CharFile):字符串;
变量
InputChar:Char;
开始
结果:='';
InputChar:=Chr(0);
虽然不是Eof,但请不要开始
读取(S,InputChar);
//接下来,检查我们读取的字符是否不是“/”字符
//如果是“/”则退出此while循环
如果(输入字符“/”),则
结果:=结果+输入字符
其他的
打破
结束;
结束;
函数ExtractBookTitle(BookRecord:String):String;
变量
p:整数;
开始
结果:=副本(簿记,10,长度(簿记));
p:=Pos('-',Result);
如果p>0,则
结果:=副本(结果1,p-1);
结束;
过程AddToOutputFile(变量OutputFile:CharFile;BookRecord:String);
变量
i:整数;
开始
对于i:=1到长度(BookRecord)do
写入(输出文件、簿记[i]);
写入(输出文件“/”);
结束;
函数(BookRecord:String):String;
开始
结果:=复印件(账面记录,1,8);
结束;
函数标题匹配(PartialTitle,BookRecord:String):布尔值;
开始
结果:=Pos(PartialTitle,ExtractBookTitle(BookRecord))>0;
结束;
变量
i:整数;//字节;
s、 萨尔:档案室
program fileofcharproject;

uses crt;

const
  sContents = '02022013Rto kill a mockingbird-1301/02012014Tpeter pan-1001/02032013Thowto-2301/02012012Tmaze runner-1001/02012012Tmaze runner-1001/02012012Tmaze runner-1001/$';
  InputFileName = 'C:\Users\MA\Documents\S.Txt';
  OutputFileName = 'C:\Users\MA\Documents\Sal.Txt';

type
  CharFile = File of Char; //  this is to permit a file of char to be used
                           //  as a parameter to a function/procedure

function GetNextBook(var S : CharFile) : String;
var
  InputChar : Char;
begin
  Result := '';

  InputChar := Chr(0);
  while not Eof(S) do begin
    Read(S, InputChar);
    // next, check that the char we've read is not a '/'
    //  if it is a '/' then exit this while loop
    if (InputChar <> '/') then
      Result := Result + InputChar
    else
      Break;
  end;
end;

function ExtractBookTitle(BookRecord : String) : String;
var
  p : Integer;
begin
  Result := Copy(BookRecord, 10, Length(BookRecord));
  p := Pos('-', Result);
  if p > 0 then
      Result := Copy(Result, 1, p - 1);
end;

procedure AddToOutputFile(var OutputFile : CharFile; BookRecord : String);
var
  i : Integer;
begin
  for i := 1 to Length(BookRecord) do
    write(OutputFile, BookRecord[i]);
  write(OutputFile, '/');
end;

function ExtractPreamble(BookRecord : String) : String;
begin
  Result := Copy(BookRecord, 1, 8);
end;

function TitleMatches(PartialTitle, BookRecord : String) : Boolean;
begin
  Result := Pos(PartialTitle, ExtractBookTitle(BookRecord)) > 0;
end;

var
  i : Integer; //byte;
  s,sal: file of char;
  l1,l2: char;
  InputChar : Char;
  BookFound : Boolean;
  cs,cn,cl: integer;
  pn,ps,tot: integer;
  Contents : String;
  BookRecord : String;
  PartialTitle : String;
begin
  //  First, create S.Txt so we don't have to make any assumptions about
  //  its contents

  Contents := sContents;
  Assign(s, InputFileName);
  Rewrite(s);

  for i := 1 to Length(Contents) do begin
    write(s, Contents[i]);  // writes the i'th character of Contents to the file
  end;

  Close(s);

  cs:=0; cn:=0;  i:=0; cl:=0;

  //  Open the input file
  Assign (s, InputFileName);
  {$I-}
  Reset (s);
  {$I+}
  if IOResult <> 0 then
  begin
    writeln('Error');
    halt(2);
  end;

  //  Open the output file
  Assign (sal, OutputFileName);
  {$I-}
  Rewrite (sal);
  IOResult;
  {$I+}
  if IOResult <> 0 then
   halt(2);

  //  the following reads the BookRecords one-by-one and copies
  //  any of them which match the partial title to sal.txt

  writeln('Enter part of a book title, followed by [Enter]');
  readln(PartialTitle);
  while not Eof(s) do begin
    BookRecord := GetNextBook(S);
    writeln(BookRecord);
    writeln('Preamble : ', ExtractPreamble(BookRecord));
    writeln('Title : ', ExtractBookTitle(BookRecord));
    if TitleMatches(PartialTitle, BookRecord) then
      AddToOutputFile(sal, BookRecord);
  end;

  //  add file '$' to sal.txt
  write(sal, '$');

  Close(sal);
  Close(s);

  writeln('Done, press any key');
  readln;

end.