程序引发未知错误:EConvertError

时间:2020-08-19 14:25:08

标签: pascal freepascal

我正在尝试创建一个程序,该程序需要用户输入并检查其有效期是否为日期(2000年至2099年)。当我对代码进行错误测试时,我连续两次将Enter输入作为输入,第一次输入Enter时,未引发任何错误,但第二次控制台闪烁消息并崩溃。我拍了一张截图,因为它崩溃了,这是它显示的错误

An unhandled exception occured at $0040CDE1
EConvertError : "" is an invalid integer

我最好的猜测是该错误是由我的StrToInt中的一个人EConvertError引起的,但是我不清楚为什么它只在第二遍而不是第一遍中抛出。我怀疑该错误发生在85、98、111或195的任一行上。

当我最初编写该程序时,a是Pascal的初学者,因此我对任何草率的代码表示歉意。

下面是所有代码,如果您想自己运行。

program DateVerifierAssignment;

uses crt, sysutils;

var
    userInputArray: array[0..7] of string;  
    len, i, day, month, year: integer;
    date, userInput, stringDay, stringMonth, stringYear: string;
    errorCatch: boolean;

//DECLARING FUNCTIONS & PROCEDURES
procedure TitleScreen();
    begin
    //prints a coloured wall of text to give information like name and instructions
    WriteLn(' o-------------------------o');
    Write(' | ');TextColor(White);Write('Date Validation Program');TextColor(Cyan);WriteLn(' |');
    WriteLn(' o-------------------------o');
    WriteLn();
    WriteLn(' o-------------------------o');
    Write(' |      ');TextColor(White);Write('Instructions');TextColor(Cyan);WriteLn('       |');
    WriteLn(' o-------------------------o');
    Write(' |   ');TextColor(White);Write('Enter a date and the');TextColor(Cyan);WriteLn('  |');
    Write(' | ');TextColor(White);Write('program will verify it');TextColor(Cyan);WriteLn('  |');
    Write(' |  ');TextColor(White);Write('and convert it to its');TextColor(Cyan);WriteLn('  |');
    Write(' |        ');TextColor(White);Write('long form');TextColor(Cyan);WriteLn('        |');
    WriteLn(' o-------------------------o');
    WriteLn();
    TextColor(White);
    Write('   press any key to begin');
    
    //waits for user input then clears the screen and returns the text color to white
    ReadKey();
    ClrScr;
    end;
         
       
function DateVerification(var userInput: string): boolean;
    var
        errorLimit : boolean;
        bounds: integer;
    begin
    errorLimit := True;
    //stores the length of the string as a variable
    len := Length(userInput);
    
    //checks to see if entry is 8 chracters long and displays an error message and returns user to input screen if it doesn't fit
    if (len <> 8) and (errorLimit = True) then
        begin
        ClrScr();
        TextColor(Red);
        WriteLn('input was not the right length (8 characters)');
        TextColor(White);
        Write('make sure date fits format ');
        TextColor(LightGreen);
        WriteLn('dd/mm/yy');
        TextColor(White);
        Readkey();
        ClrScr();
        errorLimit := false;
        Dateverification := false;
        end;
    
    //spits each character into its own spot in an array
    for i := 1 to len do
          userInputArray[i - 1] := userInput[i];
            
    //tests if every slot in the array where a slash should be is a slash
    for i := 0 to len-1 do
        begin
        if (userInputArray[2] <> '/') or (userInputArray[5] <> '/') and (errorLimit = true) then
            begin
            ClrScr();
            TextColor(Red);
            WriteLn('input did not have slashes in correct locations ');
            TextColor(LightGreen);
            WriteLn('dd/mm/yy');
            TextColor(White);
            Readkey();
            ClrScr();
            errorLimit := false;
            Dateverification := false;
            end;
        end;
        
    year := ((StrToInt(userInputArray[6]))*10) + StrToInt(userInputArray[7]);
    if (year < 1) or (year > 99) and (errorLimit = true) then
        begin
        ClrScr();
        TextColor(Red);
        WriteLn('year was not from 0 to 99');
        TextColor(White);
        Readkey();
        ClrScr();
        errorLimit := false;
        Dateverification := false;
        end;
        
    month := ((StrToInt(userInputArray[3]))*10) + StrToInt(userInputArray[4]);
        if (month < 1) or (month > 12) and (errorLimit = true) then
        begin
        ClrScr();
        TextColor(Red);
        WriteLn('month was not from 1 to 12');
        TextColor(White);
        Readkey();
        ClrScr();
        errorLimit := false;
        Dateverification := false;
        end;
    
    day :=  ((StrToInt(userInputArray[0]))*10) + StrToInt(userInputArray[1]);
    if (month = 4) or (month = 6) or (month = 9) or (month = 11) then
        bounds := 30;
    
    if (month = 2) then
        begin
        if (IsLeapYear(year) = true) then
            bounds := 29
        else
            bounds := 28;
        end
    else
        bounds := 31;    
    
    if (day < 1) or (day > bounds) and (errorLimit = true) then
            begin
            ClrScr();
            TextColor(Red);
            WriteLn('day was not from 1 to days in month');
            TextColor(White);
            Readkey();
            ClrScr();
            errorLimit := false;
            Dateverification := false;
            end;
    
    if (errorLimit = true) then  
        DateVerification := True;   
    end;    


function IsLeapYear(var year: integer): boolean;
//simple function to determine if a year is a leap year on the gregorian calender
    begin
        if (year mod 4) = 0 then
            if (year mod 100 <> 0) then
                if (year mod 400 = 0) then
                    IsLeapYear := true
                else
                    IsLeapYear := false
            else
                IsLeapyear := false
        else
            IsLeapyear := false    
    end;


procedure DateToAlpha(var userInput: string);
    begin
    
    end;
    

//MAIN PROGRAM
begin
    //preparing for while loop later in code and changes text colour to cyan
    errorCatch := true;
    TextColor(Cyan);
    
    //Displays a title screen and instruction about how to use(stored in a procedure to help with readability)
    TitleScreen();
     
    //begins a loop so that if an error is to occur the program can easily ask for a new date and try again
    while (errorCatch = true) do
        begin
        //sets error catch to 0 so that if there a no errors the program will not loop
        errorCatch := false;
        
        //displays information on how to input a date as well as an example with different colours for better readability
        Write('Enter a date in the format');TextColor(LightGreen); WriteLn(' dd/mm/yy');TextColor(White);
        Write('e.g. ');TextColor(LightGreen);WriteLn(' 09/07/20'#13#10);TextColor(White);
        
        //takes date user inputs and stores it
        ReadLn(userInput); 
        
        //calls the date verification function to see if the date is valid        
        //(refer to dateVerification at the top of the program for more info and comments)
        if (DateVerification(userInput) = false) then
            errorCatch := true;
            
        len := Length(userInput);
        for i := 1 to len do
          userInputArray[i - 1] := userInput[i];
        
        year := ((StrToInt(userInputArray[6]))*10) + StrToInt(userInputArray[7]);
        readKey();
        end;   
end.

1 个答案:

答案 0 :(得分:3)

通常在SO上,我们不提供对qs的完全编码答案,这显然是课程的工作。

在这种情况下,我以为我会例外,因为很明显您在 不必要的恶劣天气,以及您编码的方式实际上可能会妨碍您 调试并使其正常工作。

因此,以下示例显示了一个非常简单的例子, 验证以dd / mm / yyyy格式提供的21世纪日期的简洁方法。它 显示正确的处理和验证步骤顺序;如果检测到错误 在任何步骤中,它都会说明问题所在并停止。如果执行一直持续到最后, 提供的日期字符串必须有效。

我故意遗漏了任何循环 或美化代码,因为首先正确无误是一件很简洁的事情 处理和验证步骤的编码。如果您想使用循环,那很好,但是您使用的方式 例如errorCatch,我敢打赌,如果您在6个月内回到代码中,您将不记得如何 它应该工作。您不需要任何复杂的标志或循环来执行此任务-用户只需要能够准确键入八个字符(后接[Enter]),然后代码就会告诉您它是否有效。

请注意,我已经使用了标准的“复制”功能来分离出 输入的日期。顺便说一句,你的声明

userInputArray: array[0..7] of string;

完全是错误的。如果您想要一个由一定数量的字符组成的数组,可以,但是 只是不必要地使用户输入内容的处理和处理复杂化。很远 更简单,因此不太容易接受8个字符的单个 string 字符串 并处理。但是无论如何,要允许字符串在日期和月份的数字后包含/字符,字符串的长度应为10,而不是8,以允许这些数字和四年的数字。

program DateVerification;

uses
  SysUtils;

var
  sUserInput,
  sDay,
  sMonth,
  sYear : String;
  iDay,
  iMonth,
  iYear,
  iDays: Integer;
  bIsLeapYear : Boolean;

function DaysInMonth(iMonth, iYear : Integer) : Integer;
begin
  Result := -1; //  you supply the code for this taking into account leap year for February
end;

begin
  writeln('Please enter a date between 01/01/2000 and 31/12/2099 in the format shown');
  readln(sUserInput);
  if Length(sUserInput) <> 10 then begin
    writeln('Input is wrong length.');
    Halt;
  end;
  if (sUserInput[3] <> '/') or (sUserInput[6] <> '/') then begin
    writeln('Input is incorrectly delimited.');
    Halt;
  end;

  sDay := Copy(sUserInput, 1, 2);
  sMonth := Copy(sUserInput, 4, 2);
  sYear := Copy(sUserInput, 7, 4);

  iYear := StrToInt(sYear);
  if (iYear < 2000) or (iYear > 2099) then begin
    writeln('Invalid year : ', sYear);
    Halt;
  end;

  bIsLeapYear := IsLeapYear(iYear); //  you supply the code for IsLeapYear

  iMonth := StrToInt(sMonth);
  if (iMonth < 1) or (iMonth > 12) then begin
    writeln('Invalid month : ', sMonth);
    Halt;
  end;

  iDay := StrToInt(sDay);

  if (iDay < 1) or (iDay > DaysInMonth(iMonth, iYear)) then begin
    //  You need to supply the DaysInMoth function, which of course
    //  needs to account for February in a leap year
    writeln('Invalid day of month: ', sMonth);
    Halt;
  end;

  writeln(sUserInput, ' is a valid date.');
  readln;

end.