You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pascal日期验证程序EConvertError异常问题求助

解决你的Pascal日期验证程序崩溃问题

你的问题很清晰:连续两次输入回车(空字符串)后程序崩溃,报错EConvertError:""是无效整数,这确实是空字符串被传入StrToInt函数导致的异常。咱们一步步拆解原因和修复方案:

崩溃的核心原因

当你输入空字符串时,程序没有提前拦截这个无效输入,直接尝试处理空内容:

  1. 第一次回车:进入DateVerification函数后,首先触发len <> 8的判断(空字符串长度为0),程序弹出错误提示后返回false,errorCatch被设为true,循环回到输入步骤。此时还没走到StrToInt的调用,所以没崩溃。
  2. 第二次回车:同样进入DateVerification,但主程序里在验证失败后依然执行了year := ((StrToInt(userInputArray[6]))*10) + StrToInt(userInputArray[7]);这行代码。此时userInput是空字符串,userInputArray[6]和userInputArray[7]都是空字符串,调用StrToInt("")直接抛出未处理的转换异常,导致程序崩溃。

另外,DateVerification函数本身也有隐患:如果输入长度不足8(比如空字符串),后续访问userInputArray[6]、userInputArray[3]等位置时,数组元素是空字符串,一旦走到StrToInt调用也会崩溃,只是第一次回车时提前触发了长度判断,没走到那一步而已。

具体修复步骤

1. 先拦截空输入

在主程序读取输入后,第一时间检查是否为空,直接提示错误并重新循环:

ReadLn(userInput);
// 新增:拦截空输入
if userInput = '' then
begin
  ClrScr();
  TextColor(Red);
  WriteLn('输入不能为空,请重新输入!');
  TextColor(White);
  Readkey();
  ClrScr();
  errorCatch := true;
  continue; // 跳过后续代码,直接回到循环开头
end;

2. 修复DateVerification函数的逻辑漏洞

在函数开头先检查输入是否为空,并且确保所有StrToInt调用都在输入有效的前提下执行:

function DateVerification(var userInput: string): boolean;
var
  errorLimit : boolean;
  bounds: integer;
begin
  errorLimit := True;
  DateVerification := False; // 默认返回false,直到所有验证通过
  
  // 新增:先检查空输入
  if userInput = '' then
  begin
    ClrScr();
    TextColor(Red);
    WriteLn('输入不能为空,请重新输入!');
    TextColor(White);
    Readkey();
    ClrScr();
    errorLimit := false;
    Exit;
  end;
  
  len := Length(userInput);
  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;
    Exit;
  end;
  
  // 分割字符到数组
  for i := 1 to len do
    userInputArray[i - 1] := userInput[i];
  
  // 检查斜杠位置
  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;
    Exit;
  end;
  
  // 所有StrToInt调用都在errorLimit为true的前提下执行
  if errorLimit then
  begin
    year := ((StrToInt(userInputArray[6]))*10) + StrToInt(userInputArray[7]);
    if (year < 0) or (year > 99) then // 修正:yy格式应该是0-99,原代码写的1-99
    begin
      ClrScr();
      TextColor(Red);
      WriteLn('year was not from 0 to 99');
      TextColor(White);
      Readkey();
      ClrScr();
      errorLimit := false;
      Exit;
    end;
    
    month := ((StrToInt(userInputArray[3]))*10) + StrToInt(userInputArray[4]);
    if (month < 1) or (month > 12) then
    begin
      ClrScr();
      TextColor(Red);
      WriteLn('month was not from 1 to 12');
      TextColor(White);
      Readkey();
      ClrScr();
      errorLimit := false;
      Exit;
    end;
    
    day := ((StrToInt(userInputArray[0]))*10) + StrToInt(userInputArray[1]);
    // 月份天数判断
    if (month = 4) or (month = 6) or (month = 9) or (month = 11) then
      bounds := 30
    else if (month = 2) then
    begin
      if IsLeapYear(year) then
        bounds := 29
      else
        bounds := 28;
    end
    else
      bounds := 31;
      
    if (day < 1) or (day > bounds) then
    begin
      ClrScr();
      TextColor(Red);
      WriteLn('day was not from 1 to days in month');
      TextColor(White);
      Readkey();
      ClrScr();
      errorLimit := false;
      Exit;
    end;
  end;
  
  if errorLimit then
    DateVerification := True;
end;

3. 移除主程序中多余的StrToInt调用

主程序里在DateVerification之后的那几行StrToInt代码是多余的,而且是第二次崩溃的直接原因,直接删掉:

// 删掉以下代码块
len := Length(userInput);
for i := 1 to len do
  userInputArray[i - 1] := userInput[i];
year := ((StrToInt(userInputArray[6]))*10) + StrToInt(userInputArray[7]);

4. 修复IsLeapYear函数的逻辑

你的IsLeapYear参数是yy格式的年份(0-99),但实际要判断的是2000-2099的完整年份,需要转换为完整年份后再判断,否则像00(2000年)这样的年份会判断错误:

function IsLeapYear(year: integer): boolean; // 不需要var参数,因为不修改原变量
var
  fullYear: integer;
begin
  fullYear := 2000 + year;
  if (fullYear mod 4 = 0) then
  begin
    if (fullYear mod 100 = 0) then
      IsLeapYear := (fullYear mod 400 = 0)
    else
      IsLeapYear := true;
  end
  else
    IsLeapYear := false;
end;

额外的小建议

  • 尽量避免使用全局变量(比如userInputArray、len、year等),可以把它们放到函数内部,减少变量冲突的风险。
  • 可以用TryStrToInt替代StrToInt来安全转换,避免抛出异常,比如:
    var digit: integer;
    if not TryStrToInt(userInputArray[6], digit) then
    begin
      ClrScr();
      TextColor(Red);
      WriteLn('年份输入不是有效数字!');
      TextColor(White);
      Readkey();
      ClrScr();
      errorLimit := false;
      Exit;
    end;
    

这样可以处理用户输入非数字字符的情况,让程序更健壮。

内容的提问来源于stack exchange,提问作者Chibi Ayano

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 20:48:12