คราวที่แล้วพูดถึงโปรแกรมย่อยไปแล้ว คราวนี้จะมาต่อที่ฟังก์ชันอีกแบบนึงนะครับ
2. ฟังก์ชันแบบฟังก์ชัน(??)
อย่าเพิ่งสับสนกับเรื่องคำเรียกนะครับ เพราะเอาเข้าจริงๆ อีกหน่อยเราก็จะใช้ปนๆกันไปเอง
ฟังก์ชันต่างกับโปรแกรมย่อยตรงที่มีการคืนค่าครับ
อย่างที่เราเปรียบเทียบไปคราวก่อน โปรแกรมย่อยเป็นเหมือนเครื่องจักรสำหรับ "ทำงาน" ครับ คือสร้างไป พอจะใช้ ก็เหมือนเรียกให้มันทำนู่นทำนี่ มีข้อดีคือสร้างครั้งเดียว ใช้งานได้หลายครั้ง
ฟังก์ชันต่างกันครับ มันเป็นเหมือนเครื่องจักรสำหรับ "ผลิต" หรือ "คำนวณ" มากกว่า หน้าที่ของมันคือรับ input เข้าไป ประมวณผล แล้วตอบ output ออกมา เหมือนกับเครื่องจักรหรือโรงงานผลิต ที่เราโยนวัตถุดิบเข้าไป มันจะให้ผลิตภัณฑ์ออกมาครับ
แยกระหว่างฟังก์ชันกับโปรแกรมย่อยไม่ออกก็ไม่เป็นไรนะครับ
ถ้าในภาษาซี ก็คือเปรียบเหมือนการสร้างโปรแกรมย่อย มีการส่งค่าบางอย่างให้ (เรียกค่าที่ส่งให้พารามิเตอร์ ในโปรแกรมแฟคทอเรียล พารามิเตอร์ก็คือค่า n นั่นเอง) แต่ให้โปรแกรมคืนผลลัพธ์ออกมา สังเกตว่าในโปรแกรมแฟคทอเรียล มันไม่ได้ "คืน" อะไรออกมาเลยนะครับ รับค่าเข้าไปประมวลผล แล้วก็ printf ออกไปเลย
การทำโปรแกรมย่อยให้เป็นฟังก์ชันทำได้โดยการให้มัน "return" ค่าครับ ดูตัวอย่างนะครับ
1: int factorial(int n)
2: {
3: int i;
4: int fact;
5: for(i = 1, fact = 1; i <= n; i++) fact = fact * i;
6: return fact;
7: }
สังเกตว่าโปรแกรมนี้ทำงานเหมือนโปรแกรม factorial แบบโปรแกรมย่อยทุกอย่าง ต่างกันที่บรรทัดที่ 1 กับ 6 ครับ บรรทัดที่ 1 เราเปลี่ยนคำว่า "void" เป็น "int" ซึ่ง void มีความหมายว่า "ไม่มีการคืนค่า" ครับ ก็คือทำงานเป็นโปรแกรมย่อยปกติ แต่ถ้าตรงนี้เขียนว่า int หมายถึงมีการคืนค่าเป็น int ออกไปครับ
ให้มาดูต่อที่บรรทัดที่ 6 จากเดิมที่ให้ printf ออกไปเลย เราเปลี่ยนเป็นการคืนค่าครับ
ความแตกต่างก็คือ โปรแกรมย่อยเราให้มันไป "ทำงาน" ครับ ซึ่งงานที่เราให้มันทำตอนแรก ก็คือบอกผู้ใช้ว่า factorial ของค่านั้นๆเป็นเท่าไหร่ เวลาเรียกใช้แบบเดิม เราก็แค่เรียก factorial(...); มันก็จะแสดงข้อความออกไปให้เรียบร้อย
แต่ฟังก์ชันไม่ใช่ครับ มันทำการ "คืนค่า" ออกไป เวลาเรียกเราต้องเรียกแบบนี้ครับ
x = factorial(...);
โดย x เป็นตัวแปรประเภท int ที่เราประกาศขึ้นใหม่
ผลลัพธ์ก็คือ เราจะได้ค่าของ factorial ของเลขนั้นๆไปเก็บไว้ในตัวแปร x ครับ มันทำหน้าที่เหมือนเครื่องคำนวณ ที่คืนตัวเลขผลลัพธ์ออกมา ไม่ได้มีการ printf ออกไปแต่อย่างใด
ข้อดีของมันก็คือ สิ่งที่มันทำมีแค่คำนวณตามที่เราสั่ง แล้วเราสามารถเอาค่านั้นไปใช้ต่อได้ เช่นเมื่อเราเก็บค่าลงไปในตัวแปร เราอาจจะเอาตัวแปรไปคำนวณอะไรอย่างอื่นได้ตามใจเรา ต่างกับโปรแกรมย่อย ที่ไป printf ให้เสร็จสรรพ แต่เราเอาค่าอะไรไปใช้ต่อไม่ได้
ตัวอย่างเช่น เราสามารถทำอะไรแบบนี้ได้ใน main
x = factorial(5);
y = factorial(7);
printf("Factorial of 5 times factorial of 7 is %d\n", x * y);
หรืออาจเขียนแบบรวดรัดแบบนี้
printf("Factorial of 5 times factorial of 7 is %d\n", factorial(5) * factorial(7));
ซึ่งถ้าใช้โปรแกรมย่อย (เป็น void = ไม่มีการคืนค่า) เราจะทำไม่ได้ครับ แต่ถ้าเราทำเป็นฟังก์ชัน (ประกาศแบบ int) พอมันคำนวณเสร็จแล้ว มันก็จะคืนค่าออกมา เอาไปคำนวณต่อได้ครับ
ไม่จำเป็นต้องเป็น int เท่านั้นนะครับ ตัวแปรประเภทอื่นได้หมด อยากให้คืนค่าเป็นตัวอักศร ก็ประกาศเป็น char ก็ได้
ใช้ปน ๆ กันได้มั้ย แบบว่า ทั้ง printf ออกไปด้วย คืนค่าด้วย
คำตอบคือ ได้ครับ! อย่างที่บอก พอเราใช้ๆไป เราก็จะเริ่มไม่สนใจว่ามันเปฯโปรแกรมย่อย หรือฟังก์ชัน มันแล้วแต่งานว่าเราอยากเขียนมันขึ้นมาทำอะไรบ้าง แล้วอยาก return อะไรออกไปมั้ย บางทีเราอาจจะให้มันทำงานเหมือนโปรแกรมย่อยทุกอย่าง เพียงแต่ช่วย return เป็นเลข 1 หรือ 0 แค่เพื่อบอกว่าทำงานสำเร็จมั้ย อะไรทำนองนั้น อย่าง factorial เราอาจจะให้มันทั้ง printf ออกมาแล้วก็ return ออกมาด้วยเลยก็ได้ แล้วแต่เรา ที่อธิบายแยกเป็นสองอย่างเพื่อให้เข้าใจไปเป็นลำดับเท่านั้นเองครับ (หรือทำให้งงมากขึ้นหว่า 55555)
เวลาเขียนโปรแกรมก็ไม่มีอะไรแตกต่างครับ จำแค่ว่าไม่อยาก return อะไร ก็เขียนเป็น void อยาก return ก็เขียนตาม type ที่อยาก return
ถึงตรงนี้ มีใครสังเกตมั้ยครับว่า main ก็เป็นฟังก์ชันหนึ่งเหมือนกัน!!!
มันเป็นฟังก์ชันเหมือนฟังก์ชันอื่นๆทุกประการครับ โดยเมื่อเรารันโปรแกรม มันจะทำงานเป็นฟังก์ชันแรกเท่านั้นเอง
ส่วนผู้ที่เรียก main ก็คือระบบปฏิบัติการครับ
บางคนที่ใช้คอมไพเลอร์เก่าๆ อาจจะเขียน main เป็น void เพราะมันไม่ได้ต้อง return ค่าให้ใคร แต่คอมไพเลอร์ใหม่ๆจะบังคับให้เขียนเป็น int ครับ (ทำให้เราต้อง return 0; ตอนท้ายโปรแกรม) โดยค่าที่ return จะถูกส่งให้ระบบปฏิบัติการ
อาจจะเขียนงงๆนะครับ ไม่ค่อยมีเวลาปรับแต่งภาษาซักเท่าไหร่ 555+ ใครสงสัย ไม่เข้าใจ หรือเข้าใจแต่อยากแนะนำอะไร ส่งอีเมล์มาได้ที่ molev.mt@gmail.com นะครับ ยินดีตอบทุกคำถามและรับฟังทุกคำติชม : ))))
edit @ 25 Jan 2012 19:00:22 by Mistertun