VB用户转型到Free Pascal和Lazarus

Free Pascal和Lazarus专门创建了一个wiki页面,帮助大家从从 Visual Basic 切换到 Free Pascal(Lazarus 使用的 Pascal 方言和编译器)。尽管 VB 和 Pascal 有表面上的相似之处,但这两种语言却有很大的不同。由于开始使用 Pascal 的 VB 程序员在尝试做一些在 VB 中具有 Pascal 不提供的好语法的事情时立即面临困难,wiki专门帮大家关注和了解这些差异。

同时本人是带着问题学习Free Pascal,发现程序中有些语句带分号,有些语句不带分号,非常困惑。询问了AI,发现答的和例子代码不一致,更加糊涂了。所以学这个wiki的同时,也就学了Pascal的语法。

Pascal for Visual Basic users:Pascal for Visual Basic users - Lazarus wiki

值的比较和分配

Pascal 中的值是使用 = 运算符进行比较的。

Pascal 中的值是使用 := 运算符分配的(添加了 :)。

例如:

if a = 1 then b := 2;

开始和结束语句

Pascal 代码块没有用于函数、过程、循环等的区分结束语句。Pascal 只需要开始和结束(begin and end)。您可以轻松地在结束语句后手动添加注释,以阐明哪个命名例程对应于此特定end;语句。

For example:  例如:

for i := 0 to 100 do
begin
   ...
end; // for i do

Variables 变量

Declaring variables 声明变量


在 Pascal 中,所有变量都必须在使用之前声明,并且您必须在特殊的 var 部分中进行声明,该部分必须位于使用该变量的代码之前。不能在代码中间声明新变量。

For example:  例如:

procedure VarDecl;
var
  MyVar1: string;
  Myvar2, MyVar3: integer; //Multiple variables can be declared on the same line.
begin
  WriteLn('Print something');
  var MyVar4: string = 'else'; // This declaration is not allowed here - it must be moved three lines above to the var section
  WriteLn('Print something ', MyVar2);
end; //VarDecl

这段代码显然会报错,因为在begin程序体里定义了变量。当然实践中还有报错:"BEGIN" expected but "end of file" found

最终的调试结果就是又增加一对begin end代码才行

procedure VarDecl;
var
  MyVar1: string  = '';
  MyVar2: integer = 0;
begin
  WriteLn('Print something');
  MyVar2 := 360;
  WriteLn('Print something ', MyVar2);
end; //VarDecl

begin
  VarDecl;
end.

将这段代码写入vb_pascal.fpc文件,然后执行fpc vb_pascal.fpc进行编译:

fpc vb_pascal.fpc
Free Pascal Compiler version 3.2.2 [2024/04/04] for x86_64
Copyright (c) 1993-2021 by Florian Klaempfl and others
Target OS: FreeBSD for x86-64
Compiling vb_pascal.fpc
vb_pascal.fpc(3,3) Note: Local variable "MyVar1" is assigned but never used
Linking vb_pascal
/usr/local/bin/ld.bfd: warning: /usr/local/lib/fpc/3.2.2/units/x86_64-freebsd/rtl/prt0.o: missing .note.GNU-stack section implies executable stack
/usr/local/bin/ld.bfd: NOTE: This behaviour is deprecated and will be removed in a future version of the linker
13 lines compiled, 0.1 sec
1 note(s) issued

然后执行./vb_pascal即可:

./vb_pascal 
Print something
Print something 360

可以看到程序最终实现了原代码中的目标。

Types of variables 变量的类型

除了 VB 中已知的变量外,Free Pascal 还支持无符号整数(unsigned integers)。您应该特别注意不要将它们与有符号整数混合使用。

Loops 循环

Free Pascal 有四种循环。

for... do...  

while... do 

repeat... until 

for.. in.. 


注意:在FPC中,有“继续”(  Continue)过程可跳转到循环的末尾。

For... do... 

这与 VB中的For..Next循环很像,但在语法上受到更多限制。以下限制适用于 Pascal:

1. for 循环计数器必须是整数(不能是浮点类型)。

2. 没有 Step 属性。要模拟 VB Step 语法,您必须自己引入第二个计数器变量。

3. 要将循环计数器的值从正值递减,请使用关键字 DOWNTO 代替 TO。

例如:

procedure ForLoop;
var
  i: integer;
begin
  for i := 50 downto 0 do
  begin
     ...
  end; // for i
end.   // procedure ForLoop打

当然最终调通的代码是这样的:

procedure ForLoop;
var
  i: integer;
begin
  for i := 50 downto 0 do
  begin
    Write(i);  
  end; // for i
end;   // procedure ForLoop

begin
  ForLoop;
end.

4. 在Lazarus中,当索引是一个字节时,可以向下循环,这在VB6中是不可能的。

procedure ForLoop;
var
  i: byte;
begin
   for i := 200 downto 195 do
   begin
      ShowMessage (IntToStr (i));
   end;
end;

这段代码估计要在Lazarus中使用才行,如果在纯命令行执行FreePascal,则代码要修改成:

procedure ForLoopbyte;
var
  i: byte;
begin
   for i := 200 downto 195 do
   begin
      Write(i);
   end;
end;

begin
  ForLoopbyte;
end.

5. 计数器的值(上例中的 i)不能在循环中以编程方式更改。尝试这样做将引发编译器错误。相反,可以使用 Continue 来跳过循环的执行:

procedure ForLoop;
var
  i: integer;
begin
  for i := 0 to 5 do
  begin
    if i=2 then Continue; //Following part of the loop will not be executed
    ShowMessage (IntToStr (i));
  end; // for i
end.   // procedure ForLoop

当然代码最终还要调整下:

procedure ForLoopcon;
var
  i: integer;
begin
  for i := 0 to 5 do
  begin
    if i=2 then Continue; //Following part of the loop will not be executed
    Write (i);
  end; // for i
end;   // procedure ForLoop

begin
  ForLoopcon;
end.

6. 为了中断循环的执行,可以使用 Break。

procedure ForLoop;
var
  i: integer;
begin
  for i := 0 to 5 do
  begin
    if i=2 then 
    begin
      ShowMessage (IntToStr (i));
      break;
    end; //if
  end; // for i
end.   // procedure ForLoop

老规矩,还是给出实践的代码:
procedure ForLoopbreak;
var
  i: integer;
begin
  for i := 0 to 5 do
  begin
    if i=2 then 
    begin
      Write(i);
      break;
    end; //if
  end; // for i
end;   // procedure ForLoop

begin
  ForLoopbreak;
end.
 
   

Functions and procedures 职能和程序

函数输出以以下形式提供:

Result:=Value

请注意,Result:= 不充当返回( Return)。函数在分配后不会退出。

退出应该使用

exit(Value)

Visibility 能见度

在 FPC 中,一个函数或一个过程无法看到在它之后编写另一个函数或过程。

Example:  例:

procedure Proc1;
begin
  Proc2;  //This is not possible
end;

procedure Proc2;
begin
  Proc1; //This is possible
end;

To enable visibility, disregarding writing order, functions and procedures have to be declared.
为了实现可见性,不考虑写入顺序,必须声明函数和过程。

unit MyUnit;
...
procedure Proc1;
procedure Proc2;
...
implementation

procedure Proc1;
begin
  Proc2;  //This is possible now
end;

procedure Proc2;
begin
  Proc1; //This is possible
end;

在函数和过程中使用默认参数

In Pascal functions and procedures it is possible for parameters to automatically take default values. However, in the parameter list the parameters that might take default values must be declared as a contiguous list at the end of the parameter declaration part. Also, when a routine with default parameter(s) is subsequently called in your code, you can only specify non-default values beginning at the first parameter which would otherwise take a default value. You cannot specify a non-default value for a later parameter, if there are preceding parameters you have to specify values for which have not also been specified explicitly in the function or procedure call.
在 Pascal 函数和过程中,参数可以自动采用默认值。但是,在参数列表中,可能采用默认值的参数必须在参数声明部分的末尾声明为连续列表。此外,当随后在代码中调用具有默认参数的例程时,您只能指定从第一个参数开始的非默认值,否则将采用默认值。不能为后面的参数指定非默认值,如果存在前面的参数,则必须指定尚未在函数或过程调用中显式指定的值。

For example:  例如:

If a procedure is declared (correctly) as follows with two default parameters:
如果使用两个默认参数(正确)声明过程,如下所示:

procedure SampleProc(parm1: integer; parm2: string= 'something'; parm3:Boolean= True);
begin
end. //proc

it is not possible to call SampleProc as in VB like this:
不能像在 VB 中那样调用 SampleProc,如下所示:

  SampleProc(5,,False);

这将产生编译器错误。


调用过程(或函数)时,如果指定具有默认值的参数,则还必须指定其前面具有默认值的所有参数。因此,在上面的示例中,如果您希望第三个参数为 False,则还必须指定第二个参数的值。

这些是有效的调用:

  SampleProc(5,'something',False);

  SampleProc(5,'nothing');

  SampleProc(5,'');

  SampleProc(5);

Dynamic arrays 动态数组

在 Pascal 中,动态数组的最小索引为 0,即 MyArray (1) 将返回名为 MyArray 的数组的第二个元素。

使用以下方法调整数组的大小:

setlength (MyArray, NewDimension);

SetLength 不会清除数组,即它的作用类似于 ReDim Preserve,而不是 ReDim。

翻译一些常用的命令

DoEvents = TApplication.ProcessMessages

var
  app: TApplication;
  i: integer;
begin
  app := TApplication.Create(nil);

  for i := 0 to 1000000 do
  begin
    app.ProcessMessages; // Handling process messages.
    OutputDebugString(PChar(IntToStr(i)));
  end
end;

OutputDebugString 将数字打印到事件日志时,您可以在不冻结的情况下使用 Form 执行任何事件,除非您关闭表单,您必须等待循环直到完成。

在 FPC/Lazarus 中不存在的VB 命令

Split拆分 - Split不是 FPC 中的单独功能。应按以下方式使用:

String1D := '1;2,3;4;5,6'.Split([',',';']);

Join 的工作方式如下:

MyString := ''.Join(';',String1D);

Debugging

Lazarus IDE has no Instant panel.

In order to debug in Windows the dos prompt windows shall be enabled the following way: Lazarus IDE-> Main menu -> Project -> Project options... -> Compiler Options -> Config and Target -> uncheck Win32 gui application (-WG)
为了在 Windows 中调试 dos 提示符窗口应按以下方式启用: Lazarus IDE-> 主菜单 -> 项目 -> 项目选项... -> 编译器选项 -> 配置和目标 -> 取消选中 Win32 gui 应用程序 (-WG)

在 Linux 中,控制台会自行调用。

然后,可以使用 writewriteln 命令来打印调试消息。

Compiler might give some more information if the following items are checked in the IDE main menu -> Project -> Project Option -> Compiler Option -> Debugging -> -Ci, -Cr, -Co, -St, -Cr, -Sa.
如果在 IDE 主菜单中选中以下项目,编译器可能会提供更多信息 -> 项目 -> 项目选项 -> 编译器选项 -> 调试 -> -Ci、-Cr、-Co、-ST、-Cr、-Sa。

Substitution tables 替换表

VBPascalRemark
  =    :=  Becomes  
  =    =  Equal
  /    /  Float Division
  \    Div
  &    +  String concatenation  字符串连接
  MOD  Mod  Modulo operation
  <>    <>  Not equal  
  Not    Not
  And    And
  Or    Or
  Xor    Xor
  >>    Shr  bit shift right  
  <<    Shl  bit shift left  
  New line    ;  In Pascal lines end with the ; character not by a new line.  
在 Pascal 中,行以 ;字符不是换行符。
  _    No symbol is required for wrapping a line and new line symbols are acceptable within it.  
换行不需要任何符号,其中可以使用新的行符号。
  '    //  End of line Comment (only one line comment)  
行尾注释(仅一行注释)
  Exit For    Break  Interrupt execution of a loop  
中断循环的执行

VB typePascal typeSize (bits)RangeRemark
  SByte    Shortint  8-bit  -128 .. 127
  Byte    Byte  8-bit  0 .. 255
  Short  SmallInt  16-bit  -32768 .. 32767  
  Char    Word  16-bit  0 .. 65535  
  Integer    Integer  32-bit  -2147483648..2147483647  
  UInteger    Cardinal  32-bit  0 .. 4294967295
  Single    Single  32-bit  1.5E-45 .. 3.4E+38    Decimal delimiter in both languages, applied in source code is dot on the line.  
两种语言中的十进制分隔符,在源代码中应用都是行上的点。
  Double    Double  64-bit  5.0E-324 .. 1.7E+308  
  Boolean    Boolean  True False

String functions 字符串函数

VBPascalRemark
  &    +  String concatenation  字符串连接
  Format(item, formatstring)  format(formatstring, items)
format(formatstring, items)
  left(some_string,n)  左(some_string,N)  leftstr(some_string, n) or copy (some_string,1,n)
leftstr(some_string, n) 或 copy (some_string,1,n)
  Len(some_string)  Len(some_string)  length(some_string)  长度(some_string)
  LCase(some_string)  lowercase(some_string)  小写(some_string)
  Mid(some_string, startpos, numChars)  copy(some_string, startpos, numChars)
  StrReverse(string)  See Palindrome
  UCase(some_string)  uppercase(some_string)  大写(some_string)

Component prefixes

There is a list of component prefixes for Delphi, which can be used in Lazarus. Using them might provide better code readability.
有一个 Delphi 的组件前缀列表,可以在 Lazarus 中使用。使用它们可能会提供更好的代码可读性。

It is also usual to start the name of a type with the capital letter T.
通常也使用大写字母 T 开始类型名称。

Arrays of controls

Unlike in VB6 and like in VB.NET arrays of controls cannot be created statically (trough the IDE), and they can be created only dynamically.
与 VB6 和 VB.NET 中的控件数组不同,控件数组不能静态创建(通过 IDE),它们只能动态创建。

Example, creating 6 buttons above each other:
例如,在彼此上方创建 6 个按钮:

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
  btnArray: array of TButton;
begin
  SetLength(btnArray, 6);
  for i := 0 to 5 do
  begin
    btnArray[i]        := TButton.Create(Self);
    btnArray[i].Left   := 0;
    btnArray[i].Top    := i * 30;
    btnArray[i].Parent := Self;
  end;
end;

Visual Basic 到 Delphi (Pascal) 转换器

调试

代码报错Syntax error, "BEGIN" expected but "end of file" found

就是这段代码:

procedure VarDecl;
var
  MyVar1: string  = '';
  MyVar2: integer = 0;
begin
  WriteLn('Print something');
  MyVar2 := 360;
  WriteLn('Print something ', MyVar2);
end; //VarDecl

终于把它调通了,最终代码是这样的:

program VarDeclProgram; 
procedure VarDecl;  
var  
  MyVar1: string;  
  MyVar2: integer;  
begin  
  MyVar1 := '';  // 正确的初始化位置  
  MyVar2 := 0;    // 正确的初始化位置  
  WriteLn('Print something');  
  MyVar2 := 360;  
  WriteLn('Print something ', MyVar2);  
end;

// end; //VarDecl
begin
//  MyVar2 := 360;  
  VarDecl;
  WriteLn('Print something 2');

end.

对于初学者来说,真的不友好。python和vb,看到一段代码,抄下来是能单独运行的,但是Free Pascal显然不行。还没有看语法文档,目前的理解就是程序需要定义一个“程序”program VarDeclProgram;  然后定义一个“过程”procedure VarDecl; ,最后去调用了这个过程VarDecl;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值