函数、过程与基础原生类型

修改上节课的dpr文件,改成如下内容

{$ifdef FPC} {$mode objfpc}{$H+}{$J-} {$endif}
{$ifdef MSWINDOWS} {$apptype CONSOLE} {$endif}
program MyProgram;
procedure MyProcedure(const A: Integer);
begin
  WriteLn('A + 10 is: ', A + 10);
end;
function MyFunction(const S: string): string;
begin
  Result := S + 'strings are automatically managed';
end;
var
  X: Single;
begin
  WriteLn(MyFunction('Note: '));
  MyProcedure(5);
  // Division using "/" always makes float result, use "div" for integer division
  X := 15 / 5;
  WriteLn('X is now: ', X); // scientific notation
  WriteLn('X is now: ', X:1:2); // 2 decimal places
end.Code language: PHP (php)
D:\fpcdemo>fpc mydemo.dpr
Free Pascal Compiler version 3.2.2 [2021/05/15] for i386
Copyright (c) 1993-2021 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling mydemo.dpr
Linking mydemo.exe
20 lines compiled, 0.0 sec, 39248 bytes code, 2484 bytes data

D:\fpcdemo>mydemo
Note: strings are automatically managed
A + 10 is: 15
X is now:  3.000000000E+00
X is now: 3.00

D:\fpcdemo>Code language: CSS (css)

如下是注释解析,非英文可能会有乱码,读者可以设置控制台中文输出

{$ifdef FPC} {$mode objfpc}{$H+}{$J-} {$endif}
{$ifdef MSWINDOWS} {$apptype CONSOLE} {$endif}
program MyProgram; 
//当前程序自定义名称 Pascal 控制台程序必须以 program 名称; 开头,之后才能写变量、过程、主执行代码

// 无返回值:过程 procedure 过程和函数要被调用才会执行,不调用的话,就只是放在这里
procedure MyProcedure(const A: Integer);
begin
  WriteLn('A + 10 =:', A + 10);
end;

// 有返回值:函数 function
function MyFunction(const S: string): string;
begin
  Result := S + '字符串由系统自动管理内存';
end;

//Object Pascal 没有 main 函数,靠最外层 begin...end. 充当程序入口。下面是程序主块
var
  X: Single; // 单精度浮点基础类型
begin 
  // 所有要执行的逻辑都写这里
  WriteLn(MyFunction('提示:'));
  MyProcedure(5);

  // 斜杠 / 做除法结果永远是浮点数;整数整除用 div
  X := 15 / 5;
  WriteLn('X is now:', X); // 会自动用科学计数法输出
  WriteLn('X is now:', X:1:2); // 限定保留2位小数
end. //末尾是 end.(带点),代表整个程序结束;Code language: Delphi (delphi)

函数和过程有一个begin 和end ,表示函数体的开始和结束,类似C C++ JAVA等语言的 { 和 }

WriteLn是往控制台中输出内容,‘ ’表示字符串,WriteLn(‘A + 10 =:’, A + 10);会依次输出字符串 A + 10 =:和后面的表达式的结果A + 10

整个程序只能有 1 个最外层 begin和end. 里面就是程序的代码,里面再去调用其他的函数和过程

X := 15 / 5;
WriteLn(‘X is now: ‘, X); // scientific notation
WriteLn(‘X is now: ‘, X:1:2); // 2 decimal places

/是浮点数除法,商也是浮点数,

前面两行是预编译命令

{$ifdef FPC} {$mode objfpc}{$H+}{$J-} {$endif}Code language: PHP (php)

属于 FPC 专属条件编译指令

  • {$ifdef FPC}:如果当前编译器是 Free Pascal,才执行中间配置
  • {$mode objfpc}:切换到 ObjFpc 语法模式
  • {$H+}:开启长字符串(现代 string,自动内存管理,必须开启)
  • {$J-}:关闭可变常量(常量不能中途修改,更安全)
  • {$endif}:条件结束

作用:只在 FPC 编译时启用现代语法;Delphi 编译器会直接跳过整段。

{$ifdef MSWINDOWS} {$apptype CONSOLE} {$endif}Code language: PHP (php)

跨平台条件编译

  • MSWINDOWS:Windows 系统下才生效
  • {$apptype CONSOLE}:指定程序为控制台程序(弹出黑窗口,而非窗口 GUI 程序) Linux/macOS 编译时会忽略这行。

核心知识点

  • string 是基础原生类型,FPC/Delphi 自动管理内存,无需手动释放
  • procedure 过程:无返回值;function 函数:有返回值,用 Result 保存输出
  • 除法区分:/ 浮点除法;div 整数整除
  • 格式化输出 变量:总宽度:小数位数 控制浮点数显示
  • 递归无参函数必须加 (),避免歧义
  • Exit(数值) 可提前指定返回值并退出函数
  • 函数可直接单独调用,无视返回结果,用于修改全局状态等副作用逻辑

函数返回值规则

  1. 内置特殊变量 Result 用来存函数返回值,读写和局部变量完全一样
function MyFunction(const S: string): string;
begin
  Result := S + 'One';
  Result := Result + 'Two';
end;
Code language: PHP (php)
  1. 老式写法可直接给函数名赋值(MyFunction := xxx),不推荐,可读性差,统一用 Result

C/C++/Java/C#, 用 = 赋值、== 判断. 但是Pascal相反用:= 表示给变量赋值,用=来做判断,和我们数学一样。

Pascal 没有 ==

替换前面例子的MyFunction为上面的函数。这个函数,就是把调用的地方传入的字符串,先末尾追加One,然后再追加Two

最终返回的字符串就是:原来字符串+One+Two

递归调用

无参函数递归必须加括号 (),区分 “调用函数” 和 “读取当前返回值”:

function SumIntegersUntilZero: Integer;
var I: Integer;
begin
  ReadLn(I);
  Result := I;
  if I <> 0 then
    Result := Result + SumIntegersUntilZero(); // 递归调用带()
end;
Code language: JavaScript (javascript)

SumIntegersUntilZero 无参函数:

  1. SumIntegersUntilZero()调用函数,执行递归,获取返回值
  2. SumIntegersUntilZero → 代表读取当前函数内部的 Result(自身返回值变量)

如果去掉括号后的代码

Result := Result + SumIntegersUntilZero;

编译器会理解为:

Result := Result + Result;

等价于 Result := Result * 2,完全失去递归逻辑,无限循环且数值疯狂翻倍。

本例子,然函数不断递归调用,直接到输入为0才退出函数。只要不为零就递归调用本身。

Exit 提前退出

  1. 无参 Exit:直接退出,返回当前已赋值的 Result
  2. Exit(值):直接指定返回值并结束函数,等效 C 语言 return x
function AddName(const ExistingNames, NewName: string): string;
begin
  if ExistingNames = '' then
    Exit(NewName); // 直接返回NewName,终止函数
  Result := ExistingNames + ', ' + NewName;
end;
Code language: PHP (php)
{$ifdef FPC} {$mode objfpc}{$H+}{$J-} {$endif}
{$ifdef MSWINDOWS} {$apptype CONSOLE} {$endif}
program MyProgram;
procedure MyProcedure(const A: Integer);
begin
  WriteLn('A + 10 is: ', A + 10);
end;

function AddName(const ExistingNames, NewName: string): string;
begin
  if ExistingNames = '' then
    Exit(NewName); 
  Result := ExistingNames + ', ' + NewName;
end;

var
  X: Single;
begin
  WriteLn(AddName('Tom','Jack'));
  WriteLn(AddName('Tom',''));
  WriteLn(AddName('','Jack'));
end.Code language: PHP (php)

函数可当作过程调用(丢弃返回值)

函数即便有返回值,也能只执行逻辑、忽略结果;适合带副作用(修改全局变量)的场景:

var
  Count, MyCount: Integer;
function CountMe: Integer;
begin
  Inc(Count); // 副作用:全局变量自增
  Result := Count;
end;
begin
  Count := 10;
  CountMe;   // 丢弃返回值,仅执行,Count变成11
  MyCount := CountMe; // 接收返回值,Count变成12
end.
Code language: PHP (php)

完整例子

{$ifdef FPC} {$mode objfpc}{$H+}{$J-} {$endif}
{$ifdef MSWINDOWS} {$apptype CONSOLE} {$endif}
program MyProgram;

var
  Count, MyCount: Integer;

function CountMe: Integer;
begin
  Inc(Count); 
  Result := Count;
end;

begin
  Count := 10;
  WriteLn(CountMe);   
  MyCount := CountMe;
  WriteLn(MyCount);
end.Code language: PHP (php)

Inc 是 Pascal(FPC/Delphi)内置标准函数,作用是变量自增 1。

var 是 Pascal 的变量声明关键字,作用:定义变量。

var
  Count, MyCount: Integer;Code language: JavaScript (javascript)

var:开启变量声明区

Count, MyCount:两个变量名

Integer:整数类型

上面例子,var里面的,全局变量,整个程序所有过程、函数都能用

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注