在 Pascal 中解析日期比逐个字符手动解析更好的方法是什么?
日期应采用 mm.dd.yyyy 格式。
取决于所使用的编译器。 如果您使用 Delphi,请查看 trystrtodate,或者(如果使用最近的 Free Pascal)尝试 dateutils.scandatetime
如果您使用 Turbo Pascal,那么您唯一能做的就是逐个字符检查字符串。 或者,您可以创建记录:
type
dater = Record
month: byte;
day : byte;
year: integer;
End;
var mydate: dater;
因此,了解格式(mm.dd.yyyy),您可以轻松验证它。 轻松访问值mydate.month、mydate.day、mydate.year。
<
、>
和=
进行词法比较;也许这对于您的应用程序来说已经足够了,因此不需要将字符转换为 integer
值。您应该注意到的一件事是基数标记,即一个点 (.
real
数字。
program readDate(input, output);
{ This is a compiler directive that is only necessary for }
{$mode ISO} { and respected by the FreePascal Compiler. }
var
dayMonth, yearFraction: real;
day, month, year: integer;
begin
readLn(dayMonth, yearFraction);
day := trunc(dayMonth);
month := trunc(dayMonth * 100) mod 100;
year := trunc(yearFraction * 1E4);
writeLn(month:1, '/', day:1, '/', year:1);
end.
但也有几个缺点, 最值得注意的是潜在的舍入错误:
Real
仅提供“合理的近似值”,因此它不一定像 integer
那样精确。如果您的处理器支持 ISO 标准 10206“扩展 Pascal”的功能,则可以结合使用其 string
program extendedReadDate(input, output);
var
line: string(12);
firstDotIndex, secondDotIndex: integer;
ts: timeStamp;
dummy: real;
begin
{ This reads up to `line.capacity` (12) characters from `input`. }
read(line);
{ An end-of-line marker is not consumed by `read`. }
if not EOLn then
begin
{ There are still characters left on the `input` line. }
writeLn('Error: date string too long.'); halt
end;
readLn;
firstDotIndex := index(line, '.');
if firstDotIndex = 0 then
begin
writeLn('Error: date string does not contain any dots.'); halt
end;
secondDotIndex := index(subStr(line, firstDotIndex), '.');
if secondDotIndex = 0 then
begin
writeLn('Error: date string does not contain a second dot.');halt
end;
{ Normalize `secondDotIndex` with respect to the entire `line`. }
secondDotIndex := firstDotIndex + secondDotIndex + 1;
然而,从扩展 Pascal 开始,所有 I/O 例程都接受 Pascal 源代码中可接受的任何格式。
这意味着用户可以输入像 2#101.8#7.36#1K8
这样的日期,字符串 2#101
等是 valid
integer
文字(在 EP 中)。
为了防止接受这样的值,我们也可以通过将字符串解析为 real
值来引发错误。
with ts do
begin
readStr(line[1..pred(firstDotIndex)], day);
readStr(line[1..pred(firstDotIndex)], dummy);
readStr(line[succ(firstDotIndex)..pred(secondDotIndex)], month);
readStr(line[succ(firstDotIndex)..pred(secondDotIndex)], dummy);
readStr(subStr(line, succ(secondDotIndex)), year);
readStr(subStr(line, succ(secondDotIndex)), dummy);
dateValid := true
end;
writeLn(date(ts));
end.