======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; | procedure SayHelloWorld; begin writeln('HelloWorld'); end; 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; | function multiply(a,b:real):real; begin result:=a*b; end; 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 ถ้ามี) ได้เลย ยกตัวอย่างเช่น 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 อื่น\\ 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; 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. \\ __**อธิบาย**__ - ตัวอย่างนี้ มีการประกาศโปรแกรมย่อย ชื่อ 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 \\