User Tools

Site Tools


Sidebar


Introduction


Basic Tutorials


Advance Tutorials


Useful Techniques


Examples

  • Simple Pipe Weight Calculator
  • Unit Convertor

Sidebar

tutorial:procedureandfunction

Procedure and Function

Procedure/Function คืออะไร

ทั้งคู่ทำหน้าที่เป็นโปรแกรมย่อยเหมือนกัน แต่มีความแตกต่างกันอยู่ดังนี้

  • Function จะส่งค่ากลับ
  • Procedure ไม่ส่งค่าใดๆกลับ


รูปแบบของ Procedure

Procedure โดยปกติจะมีอยู่ 2 แบบ คือ แบบรับค่า input กับแบบไม่รับค่า input

Topic Format
Procedure แบบไม่รับค่า Input
procedure ProcedureName;
begin
  {Do something}
end;
Procedure แบบรับค่า Input
procedure ProcedureName(Arg1,Arg2:integer; Arg3:real);
begin
  {Do something}
end;

Example-1: Procedure แบบไม่มี input

Example-1: Procedure แบบไม่มี input

procedure SayHelloWorld;
begin
  writeln('HelloWorld');
end;

Example-2: Procedure แบบมี input

Example-2: Procedure แบบมี input

procedure SayHello(Name,SurName:string; Age:integer);
begin
  writeln('Hello ',Name,' ',Surname);
  writeln('Your age is ',Age);
end;



รูปแบบของ Function

รูปแบบของ function นั้น จะคล้ายกับ procedure ทุกประการ คือมีทั้งแบบรับค่า input กับแบบไม่รับค่า input
แต่โดยทั่วไปแล้ว function มักจะถูกใช้งานโดยการรับค่า input (เพราะถ้าไม่มีการรับค่า ก็ไม่ต่างจากการใช้ค่าคงที่)
อย่างไรก็ตาม สิ่งที่ขาดไม่ได้เลยสำหรับการประกาศ function คือ ต้องมีการส่งค่า output กลับด้วยเสมอ
ตัวแปรที่ใช้รับค่าเพื่อแสดงค่า output มีได้ 2 แบบ คือ

Topic Format
Function แบบใช้ตัวแปรที่ชื่อ result เป็น Output
function FunctionName(Arg1,Arg2:integer; Arg3:real):integer;
begin
  result:= {Do something};
end;
Function แบบใช้ตัวแปรที่เป็นชื่อของฟังก์ชั่นเอง เป็น Output
function FunctionName(Arg1,Arg2:integer; Arg3:real):integer;
begin
  FunctionName:= {Do something};
end;

Example-3: Function แบบใช้ตัวแปรที่ชื่อ result เป็น Output

Example-3: Function แบบใช้ตัวแปรที่ชื่อ result เป็น Output

function multiply(a,b:real):real;
begin
  result:=a*b;
end;

Example-4: Function แบบใช้ตัวแปรที่เป็นชื่อของฟังก์ชั่นเอง เป็น Output

Example-4: Function แบบใช้ตัวแปรที่เป็นชื่อของฟังก์ชั่นเอง เป็น Output

function multiply(a,b:real):real;
begin
  multiply:=a*b;
end;


จากประสบการณ์ของผม ขอแนะนำให้ใช้ result แทนชื่อของ Function ครับ เพราะจะง่ายในการแก้ใขชื่อ Function ในภายหลัง

การประกาศและการเรียกใช้ Procedure/Function

หลังจากการประกาศ uses แล้ว Procedure/Function ที่เป็น Global Scope สามารถประกาศไว้ ณ ส่วนไหนของโปรแกรมก็ได้ แต่โดยปกติแล้ว ผมขอแนะนำให้ประกาศทีหลังสุด (หลังจากประกาศ var) แต่ถ้าหากเป็น Function/Procedure ที่มาจาก Shared Library ผมขอแนะนำให้วางไว้แรกสุด (ต่อจากการประกาศ uses)

การเรียกใช้ Procedure นั้นง่ายมาก เพียงแค่ใส่ชื่อ Procedure นั้นๆ (พร้อมกับ Input Parameters ถ้ามี) ได้เลย ยกตัวอย่างเช่น

Example-5: Calling Procedures

Example-5: Calling Procedures

Program SayHellow;

procedure HelloWorld;
begin
  writeln('HelloWorld');
end;

procedure SayHello(sName:string);
begin
  writeln('Hello'+ sName);
end;

Begin
  HelloWorld; //Calling HelloWorld
  SayHello('Mr. Smith'); //Calling Procedure
End.


สำหรับการเรียกใช้ Function นั้นก็คล้ายกับการเรียกใช้ Procedure แต่มีข้อแตกต่างอีกอย่างหนึ่ง คือ Function ให้ค่า Output ด้วย

Nested Function/Procedure

คือ Function/Procedure ที่เป็น Local Scope ซ้อนอยู่ใน Function/Procedure อื่น

Example-6: Nested Function

Example-6: Nested Function

procedure SolvePolynomial(A,B,C:real);
//This function used for solving polynomial Ax^2+Bx+C = 0
var Ans1,Ans2:real;
  function IsReal(A,B,C:real):Boolean; //Nested Function
  begin
    if (B*B-4*A*C)>= 0 then
       result:=true
     else
       result:=false;
  end;
begin
  if IsReal(A,B,C) then
    begin
      Ans1:=(-B+power(B*B-4*A*C,0.5))/(2*A); 
      Ans2:=(-B-power(B*B-4*A*C,0.5))/(2*A);
      writeln('x1 = ', Ans1);
      writeln('x2 = ', Ans2);
    end
  else
     writeln('x1 = '+ FloatToStr(-B/(2*A))+' + '+ FloatToStr(power((B*B-4*A*C)*(-1),0.5)/(2*A))+'i');
     writeln('x2 = '+ FloatToStr(-B/(2*A))+' - '+ FloatToStr(power((B*B-4*A*C)*(-1),0.5)/(2*A))+'i');
     
  //function Power() requires unit: math
  //function FloatToStr() requires unit: SysUtils
end;



Passing Parameters

การส่งผ่าน Parameters เข้าไปใน Procedure/Function มี 2 แบบ คือ By Value และ By Reference

  • By Value คือ ส่งเฉพาะค่าของ Parameter เข้าไปใน Procedure/Function โดยหากมีการเปลี่ยนแปลงค่าใดๆใน Procedure/Function นั้น จะไม่เปลี่ยนแปลงต่อค่าที่แท้จริงของ Parameter สำหรับการรับค่าแบบปกติ
  • By Reference คือ หากมีการเปลี่ยนแปลงค่าใดๆของ Parameter ใน Procedure/Function นั้น จะเปลี่ยนแปลงค่าที่แท้จริงของ Parameter ด้วย

By Value

การใส่ตัวแปรแบบทั่วไป คือ การส่งผ่าน Parameter ในแบบ By Value

  
  procedure DoItA(X:integer);
  begin
    X:=10;
    writeln('X = ',X);
  end;

By Reference

เราสามารถใส่ var หน้า Parameter เพื่อให้กลายเป็น By Reference ได้ดังนี้

  
  procedure DoItB(var X:integer);
  begin
    X:=10;
    writeln('X = ',X);
  end;

Example-7: Passing Parameters (By Value, By Reference)

Example-7: Passing Parameters (By Value, By Reference)

program Passing_Param;

var A,B:integer;

procedure DoItA(X:integer); //By Value
begin
  X:=100;
  writeln('DoItA, X = ',X);
end;

procedure DoItB(var X:integer); //By Reference
begin
  X:=200;
  writeln('DoItB, X = ',X);
end;

begin
  A:=1;
  B:=2;

  writeln('A = ',A);
  writeln('B = ',B);

  DoItA(A);
  DoItB(B);

  writeln('A = ',A);
  writeln('B = ',B);

  readln();
end. 

Compiled Results:

A = 1
B = 2
DoItA, X = 100
DoItB, X = 200
A = 1
B = 200
  


Forward Declaration

คือ การประกาศ Procedure/Function ล่วงหน้าเพื่อให้ทุก Procedure/Function สามารถเรียกใช้งานกันและกันได้หมด สาเหตุที่ต้องทำแบบนี้เพราะว่า โดยปกตินั้น Compiler จะอ่าน source code จาก บนลงล่าง ดังนั้น หากมี Procedure/Function ตัวใดตัวหนึ่งเรียกใช้งาน Procedure/Function ตัวอื่นที่ยังไม่ได้ประกาศ จะทำให้เกิด Error

รูปแบบการประกาศสำหรับ Program จะมีคำว่า forward ต่อท้ายดังนี้

Procedure DoSomething; forward;

สำหรับ Unit นั้น FPC บังคับให้ต้องมีการทำ forward declaration ทุกครั้งก่อนเสมอ เพราะ unit อื่นหรือ program ที่มีการ uses unit ดังกล่าวนั้น จะเข้าถึง Procedure/Function ได้เฉพาะส่วนที่เป็น interface เท่านั้น ไม่สามารถเข้าถึงส่วน implementation โดยตรงได้ ดังนั้นจึงต้องประกาศล่วงหน้าในตำแหน่งใต้คำว่า interface เสมอ โดยการประกาศจะไม่มีคำว่า forward ต่อท้ายเหมือนของ program อีก ดังตัวอย่างต่อไปนี้

unit Unit1;

interface
//Forward declaration
procedure First;
procedure Second;

implementation

procedure First;
begin
  writeln('Hello First');
  Second;
end;

procedure Second;
begin
  writeln('Hello Second');
end;
end. 

Example-8: Forward Declarations on Simple Program

Example-8: Forward Declarations on Simple Program

อธิบาย - ตัวอย่างนี้ มีการประกาศโปรแกรมย่อย ชื่อ Second ล่วงหน้าในบรรทัดที่ 4 เพื่อให้โปรแกรมย่อยที่ชื่อ First ได้รู้จัก Second ก่อน แน่นอนว่าหากตัด code ในบรรทัดที่ 4 ออกไปแล้ว สิ่งที่จะตามมาคือ เมื่อ compiler อ่านจนมาถึง First ก็จะฟ้องทันทีว่าไม่สามารถหา Second เจอ

program FWD_Declaration;

//Forward declarations
procedure Second;  forward;

//Implementations
procedure First;
begin
  writeln('Hello First');
  Second;
end;

procedure Second;
begin
  writeln('Hello Second');
end;

begin
  First;
  readln();
end.  

Compiled Results:

Hello First
Hello Second
  


tutorial/procedureandfunction.txt · Last modified: 2019/01/06 16:54 by admin