วันอาทิตย์ที่ 22 กันยายน พ.ศ. 2556

How to call python script by php

โอเคไม่พูดมามาเริ่มกันเลย ความต้องการคือ เขียน php อยู่แต่อยากเรียก python script ขึ้นมาใช้งาน ถามว่าทำได้ไหม คำตอบคือ "สามารถทำได้ครับ" เรามาดูวิธีทำกัน

อันดับแรกสร้างไฟล์ Python ก่อน ตั้งชื่อว่า exampleCallByPHP.py โดยมีโค๊ดดังนี้
import sys
print "Begin of Python Script\n"
print "The passed arguments are ", sys.argv
print "Show all argument"
for i in xrange(len(sys.argv)):
    print "sys.argv["+str(i)+"] => "+str(sys.argv[i])
print "\nEnd of Python Script"

อธิบายโค๊ดดังนี้

  • บรรทัดที่ 3 เป็นการแสดง argument ทั้งหมดที่ถูกส่งมาจาก PHP
  • บรรทัดที่  5-6 เป็นการเข้าถึง argument ที่ละค่าโดยใช่ for loop
อันดับที่สองสร้างไฟล์ PHP ตั้งชื่อว่า exampleCallPython.php โดยมีโค๊ดดังนี้

<?php
$param1 = "Somchai";
$param2 = "Jaidee";
$param3 = 56;
$command = "/Python27/python exampleCallByPHP.py";
$command .= " $param1 $param2 $param3";
header('Content-Type: text/html; charset=utf-8');
echo '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
$pid = popen($command,"r");
echo "<body><pre>";
while( !feof( $pid ) ) {
echo fread($pid, 256);
}
pclose($pid);
echo "</pre>";
echo "Script final";
?>

อธิบายโค๊ดดังนี้

  • $command แบ่งออกเป็น 3 ส่วน ส่วนที่ 1 คือ Path ที่ติดตั้ง Python ส่วนที่ 2 คือ Path และชื่อของไฟล์ Python ที่เขียนไว้ และส่วนที่ 3 คือ พารามิเตอร์ที่จะส่งไปพร้อมกับการเรียกไฟล์ Python ซึ่งส่วนที่ 3 ก็ไม่จำเป็นเสมอไป จะมีหรือไม่มีก็ได้
  • $pid = popen($command,"r"); คือการเรียกใช้ไฟล์ python ที่เราได้กำหนดไว้ในตัวแปร $command  ส่วน "r" คือโหมดการเรียกไฟล์ มีอยู่ 2 โหมดคือ r->อ่านอย่างเดียว, w->เขียนอย่างเดียว ส่วน $pid คือค่าที่รีเทิร์นมาจากการเรียกใช้ไฟล์ python นั่นคือสิ่งที่ไฟล์ python แสดงผลโดยคำสั่งการแสดงผลในไฟล์ python
  • while loop คือการแสดงค่าที่ได้รีเทิร์นมาจากไฟล์ python โดยเงื่อนไขของลูปคือวนไปเรื่อยๆจนหมดข้อมูลใน $pid และใช้คำสั่ง fread(file, length) ในการอ่าานค่าจาก $pid แล้วแสดงผลในหน้าเว็บ
ผลลัพธ์ที่แสดงที่หน้าเว็บเป็นดังรูป


ก็เป็นตัวอย่างเล็กๆ น้อยๆ ที่สามารถนำไปต่อยอดได้ หวังว่าคงจะเป็นประโยชน์นะครับ

วันพฤหัสบดีที่ 19 กันยายน พ.ศ. 2556

สร้าง Stack ด้วยภาษา Java (Stack Array Implementation)

จากบล็อกที่แล้วเขียนถึงเรื่อง Linked List สำหรับบล็อกนี้จะเขียนเกี่ยวกับโครงสร้างข้อมูลแบบง่ายอีกแบบหนึ่งที่น่าจะได้เรียนหรือเคยได้ยินมาก่อนบ้างนั่นคือ Stack

Stack ก็เป็นโครงสร้างข้อมูลอีกแบบหนึ่งที่สามารถช่วยให้สามารถจัดเก็บข้อมูลได้ และสามารถนำไปประยุกต์ใช้กับโปรแกรมอื่นๆได้ เช่น Balancing Symbols, Postfix Expression Calculator เป็นต้น

หลักการทำงานของ Stack เป็นหลักการง่ายๆคือ ข้อมูลที่เข้าหลังสุดจะถูกนำออกก่อน (Last Input First Output: LIFO)

โอเปอเรชันที่สำคัญของ Stack มีอยู่ 3 โอเปอเรเตอร์ ประกอบด้วย
  1. Push คือโอเปอเรชันที่ใช้สำหรับการเพิ่มข้อมูลไปยัง Stack
  2. Pop คือโอเปอเรชันที่ใช้สำหรับการลบข้อมูลจาก Stack
  3. Peek คือโอเปอเรชันที่ใช้สำหรับการดูข้อมูลที่ตำแหน่งบนสุดของ Stack นั่นคือดูข้อมูลล่าสุดที่เพิ่มเข้าไป
ในการสร้างสแตกสามารถสร้างได้จากอาร์เรย์ก็ได้ หรือสามารถใช้ Linked List ก็ได้ แต่สำหรับบล็อกนี้จะแสดงการสร้างสแตกโดยใช้อาร์เรย์

อันดับแรกก็สร้าง class Stack ขึ้นมาก่อน โดยมี Attribute ของคลาสดังรูป


อธิบายรูปคือ 
  • บรรทัดที่ 3 คือขนาดของสแตกโดยมีค่าเริ่มต้นอยู่ที่ 100 แต่สามารถกำหนดเองได้
  • บรรทัดที่ 4 คือตำแหน่งของข้อมูลที่เป็น top of stack
  • บรรทัดที่ 5 คืออาร์เรย์ที่ใช้เก็บข้อมูลเป็นชนิดข้อมูลใดก็ได้ เช่น int, float, long, double, char, String
ต่อไปเป็นการสร้างเมธอดที่จำเป็นต้องใช้ซึ่งประกอบด้วย

1. Stack() -> constructor method เขียนโค๊ดได้ดังนี้


อธิบายรูปคือ
  • บรรทัดที่ 7-9 เป็นการสร้าง constructor method โดยไม่มีพารามิเตอร์ และสร้างอารย์ของ Object ให้มีขนาดเท่ากับ maxStackSize
  • บรรทัดที่ 11-14 เป็นการสร้าง constructor method โดยรับพารามิเตอร์หนึ่งค่าคือ size ขนาดของสแตกที่ต้องการ แล้วสร้างอารย์ของ Object ให้มีขนาดเท่ากับ size ที่รับเข้ามา และกำหนดค่า size ให้กับ maxStackSize
2. initializeValueStack() เป็นเมธอดสำหรับกำหนดค่าเริ่มต้นให้กับอาร์เรย์ เขียนโค๊ดได้ดังนี้



อธิบายรูปคือ
  • บรรทัดที่ 17-18 เป็นการกำหนดค่า null ให้กับอาร์เรย์ทั้งหมดที่จะใช้เก็บข้อมูล
  • บรรทัดที่ 19 กำหนดให้ตำแหน่งของข้อมูล top of stack เท่ากับศูนย์
3. isEmpty() เป็นเมธอดสำหรับตรวจสอบว่าสแตกไม่มีข้อมูลใดๆ เลยใช่หรือไม่ โดยมี return type คือ boolean เขียนโค๊ดได้ดังนี้


อธิบายรูปคือ
  • บรรทัดที่ 23 คือการรีเทิร์นค่าที่ได้จากการตรวจสอบเงื่อนไข stackTop == 0 ถ้าเงื่อนไขนี้เป็นจริงจะรีเทิร์นค่า true และถ้าไม่จริงจะรีเทิร์นค่า false
4. isFull() เป็นเมธอดสำหรับตรวจสอบว่าสแตกเต็มหรือไม่  โดยมี return type คือ boolean เขียนโค๊ดได้ดังนี้


อธิบายรูปคือ
  • บรรทัดที่ 27 คือการรีเทิร์นค่าที่ได้จากการตรวจสอบเงื่อนไข stackTop == maxStackSize ถ้าเงื่อนไขนี้เป็นจริงจะรีเทิร์นค่า true และถ้าไม่จริงจะรีเทิร์นค่า false
5. push() เป็นเมธอดสำหรับการเพิ่มข้อมูลไปยังสแตก โดยมรการรับพารามเตอร์หนึ่งตัวคือ Object newItem เขียนโค๊ดได้ดังนี้


อธิบายรูปคือ
  • บรรทัดที่ 31-32 ตรวจสอบว่าสแตกเต็มหรือไม่ หากสแตกเต็มแล้วจะหยุดการทำงาน และแสดงคำว่า StackOverflow ออกทาง Console
  • บรรทัดที่ 33-34 เป็นผลมาจากการตรวจสอบเงื่อนไขด้านบน หากเงื่อนไขบนไม่เป็นจริง ก็จะกำหนดค่า newItem ลงในอาร์เรย์ตำแหน่งที่ stackTop และเพิ่มค่า stackTopไปอีกหนึ่ง เพื่อไปชี้ยังตำแหน่งถัดไปของอาร์เรย์
6. pop() เป็นเมธอดสำหรับการลบข้อมูลจากสแตก เขียนโค๊ดได้ดังนี้


อธิบายรูปคือ
  • บรรทัดที่ 44-45 ตรวจสอบว่าสแตกว่างหรือไม่ หากสแตกว่างไม่มีข้อมูลจะหยุดการทำงาน และแสดงคำว่า StackUnderflow ออกทาง Console
  • บรรทัดที่ 46-47 เป็นผลมาจากการตรวจสอบเงื่อนไขด้านบน หากเงื่อนไขบนไม่เป็นจริง ก็จะลดค่า stackTop ลงหนึ่งค่า แล้วกำหนดค่าให้ข้อมูลในอาร์เรย์ตำแหน่งที่ stackTop ชี้อยู่มีค่าเท่ากับ null
7. peek() เป็นเมธอดสำหรับการดูข้อมูลที่ตำแหน่งบนสุดของสแตก นั่นคือดูข้อมูลล่าสุดที่เพิ่มเข้าไป โดยมี return type คือ Object เขียนโค๊ดได้ดังนี้


อธิบายรูปคือ
  • บรรทัดที่ 38-39 ตรวจสอบว่าสแตกว่างหรือไม่ หากสแตกว่างไม่มีข้อมูลจะหยุดการทำงาน และแสดงคำว่า StackUnderflow ออกทาง Console
  • บรรทัดที่ 40 เป็นผลมาจากการตรวจสอบเงื่อนไขด้านบน หากเงื่อนไขบนไม่เป็นจริง ก็จะรีเทิร์นข้อมูลในอาร์เรย์ตำแหน่งที่ stackTop ชี้อยู่ แต่จากโค๊ดจะเห็นค่าต้องลบหนึ่งด้วย เพราะอินเด็กของอาร์เรย์ให้เริ่มที่ศูนย์
8. main() เป็นเมธอดสำหรับการเรียกใช้เมธอดอื่นๆ เขียนโค๊ดได้ดังนี้


อธิบายรูปคือ
  • บรรทัดที่ 50 สร้าง object s1  โดยใช้ constructor method แบบไม่มีพารามิเตอร์ จึงทำให้สแตกมีขนาดเท่ากับ 100 และสร้าง object s2 โดยใช้ constructor method แบบมีพารามิเตอร์ โดยส่งค่า 50 จึงทำให้สแตกมีขนาด 50
  • บรรทัดที่ 52-53 เรียกใช้เมธอด initializeValueStack() ทั้งสองออปเจ็ค
  • บรรทัดที่ 55-60 การเพิ่มค่าไปยังสแตก โดยพบว่าเพิ่มข้อมูลที่มีประเภทแตกต่างกันไปยังสแตกเดียวกันได้
  • บรรทัดที่ 61-68 พยายามแสดงค่าที่อยู่ที่ top of stack โดยใช้เมธอด peek() และลบข้อมูลที่อยู่ที่ตำแหน่ง top of stack โดยใช้เมธอด pop()

จากการยกตัวอย่างทั้งหมดนี้ทำให้สามรถสร้างสแตกอย่างง่ายขึ้นมมาใช้งานได้ และสามารถนำไปประยุกต์กับงานอื่นๆได้

โต๊ดสมบูรณ์สามารถดาวน์โหลดได้ที่นี่

วันพุธที่ 18 กันยายน พ.ศ. 2556

สร้าง Linked List ด้วยภาษา Java

Linked List เป็นโครงสร้างข้อมูลแบบง่ายที่สุดที่เราได้เรียนกันตอนวิชาโครงสร้างข้อมูล (Data Structure) 

วันนี้ผมจะแสดงตัวอย่างการสร้าง Linked List ด้วยภาษาจาวา

อันดับแรก ต้องเข้าใจก่อนว่า Linked List ประกอบกันขึ้นด้วย "โหนด" ย่อยๆ ที่เรียงต่อกัน คล้ายอาร์เรย์ที่เรารู้จักกันดี แต่สำหรับโหนดที่ว่า ไม่จำเป็นต้องมีเพียงชนิดข้อมูลเดียว สามารถมีหลายข้อมูลอยู่รวมกันในโหนดเดียวได้ แต่สิ่งสำคัญที่ต้องมีในโหนดนั้นคือ link มันสำคัญอย่างไร สำคัญเพราะว่า link เป็นตัวชี้ว่าโหนดถัดไปคือโหนดใดนั่นเอง หากขาด link ก็เท่ากับว่า เราไม่สามารถเชื่อมโยงโหนดใดๆ เข้าหากันได้


ไม่พูดมากเรามาเริ่มโค๊ดกันเลยดีกว่า ผมแบ่งการเขียนโค๊ดออกเป็น 2 ไฟล์นะครับ คือ Node.java และ LinkedList.java

- Node.java คือ ไฟล์ที่สร้างข้อมูลภายในโหนดใดๆ
- LinkedList.java คือ ไฟล์ที่สร้างโหนดใดๆ ขึ้นมาแล้วนำโหนดนั้นๆ มาเชื่อมต่อกัน

มาเริ่มกันที่ Node.java ผมจะกำหนดให้ข้อมูลในหนึ่งโหนดเป็นดังนี้นะครับ

ข้อมูลที่จะบรรจุในโหนดใดๆ (Attribute of class)

อธิบายรูปคือ โหนดใดๆ จะประกอบด้วยข้อมูลดังนี้ 
  1. String fName คือ ชื่อ
  2. String lName คือ นามสกุล
  3. String id คือ รหัสประจำตัว
  4. double score คือ คะแนนสอบ
  5. Node link คือ ตัวชี้ว่าโหนดถัดไปคือโหนดใด


และมี Constructor Method ดังนี้
Constructor Method

อธิบายรูปคือ มี constructor method อยู่ 2 แบบซึ่งได้แก่
  1. Node() เป็น constructor method ที่ไม่มีการรับพารามิเตอร์ ใช้สำหรับการกำหนดค่าเริ่มต้นให้กับข้อมูลใดๆ ในโหนดนั้นๆ
  2. Node(String fName, String lName, String id, double score, Node link) เป็น constructor method ที่มีการรับพารามิเตอร์ และกำหนดให้กับข้อมูลตามลำดับ
สำหรับไฟล์ Node.java ก็มีโค๊ดสั้นๆ เพียงเท่านี้ ต่อไปเป็นรายละเอียดของไฟล์ LinkedList.java ซึ่งการทำงานของไฟล์นี้จะแบ่งออกเป็นเมธอดย่อยๆ ดังนี้
  • insertNode ใช้สำหรับการเพิ่มโหนดเข้าไปใน Linked List
  • printLinkedList ใช้สำหรับการแสดงค่าต่างๆ ที่อยู่ใน Linked List
  • main ใช้สำหรับการรับค่า และเรียกใช้เมธอดอื่นๆ
- insertNode method เขียนโค๊ดได้ดังนี้

insertNode method
อธิบายรูปคือ insertNode method มีการรับพารามิเตอร์ทั้งหมด 5 ตัว เพื่แนำมากำหนดให้กับข้อมูลในโหนด แต่ที่สำคัญคือ Node head คือตัวกำหนดว่าต้นลิสต์อยู่ที่ใด ในการเพิ่มโหนดนี้เราใช้แบบการเพิ่มที่ท้ายลิสต์ คือการสร้างโหนดใหม่มาต่อท้ายโหนดเดิมในลิสต์ไปเรื่อยๆ และมีการรีเทิร์นค่ากลับไปเป็นชนิดข้อมูลแบบ Node คือการคืน โหนด head ที่เป็นต้นลิสต์กลับไปนั่นเอง
  • Node newNode = new Node(); คือการสร้าง newNode ให้เป็น object ของ class Node จะเห็นว่า เราเรียกใช้ constructor method แบบ Node() ซึ่งยังไม่มีการกำหนดค่าจากผู้ใช้ใดๆทั้งสิ้น แต่จะเป็นการกำหนดค่าเริ่มต้นเท่านั้น จากนั้นเริ่มทำการกำหนดค่าที่จากพารามิเตอร์ให้กับข้อมูลในโหนดตามลำดับ โดยการเข้าถึงข้อมูลต่างๆในโหนดสามารถเข้าถึงได้โดยตรง เพราะการสร้าง class Node ได้กำหนดให้ attribute ใดๆ มีการเข้าถึงแบบ public ไว้ แต่ถ้าหากมีการกำหนดการเข้าถึงข้อมูลแบบ private ไว้ เราจำเป็นต้องสร้าง method getter setter ให้กับข้อมูลทุกตัวเพื่อใช้ในการเข้าถึงข้อนั้นๆ
  • Node trav1, trav2; สร้างโหนด 2 โหนดเปล่าขึ้นมา เพื่อใช้ในการท่องเข้าไปในลิสต์
  • trav1 = trav2 = head; กำหนดให้ทั้งสองโหนดชี้ที่ต้นลิสต์
  • ใน while loop ทำการท่องเข้าไปในลิสต์ โดยให้ โหนด trav2 ท่องตาม โหนด trav1 หากในลิสต์มีข้อมูล โหนด trav2 จะหยุดที่โหนดสุดท้ายในลิสต์พอดี และจะหยุด loop ก็ต่อเมื่อ trav1 ท่องไปจนสุดลิสต์
  • trav2 = trav1; กำหนดให้ โหนด trav2 ท่องตาม โหนด trav1
  • trav1 = trav1.link; กำหนดให้ โหนด trav1 ท่องไปยังโหนดถัดไป
  • if(trav1 != trav2) trav2.link = newNode; ถ้าหาก โหนด trav1 ไม่เท่ากับโหนด trav2 แสดงว่าในลิสต์มีโหนดใดๆ อยู่ให้ โหนด trav2 ที่ชี้อยู่โหนดสุดท้ายในลิสต์ ทำการชี้ link ไปยัง โหนด newNode ซึ่งก็คือโหนดที่เพิ่มเข้ามาใหม่
  • else head = newNode; แต่ถ้าเงื่อนไข if ด้านบนไม่เป็นจริง แสดงว่าในลิสต์ยังไม่มีโหนดใดๆ เลย ก็กำหนดให้เป็นโหนดแรกของลิสต์ โดยให้ โหนด head มีค่าเท่ากับ โหนด newNode

- printLinkedList method เขียนโค๊ดได้ดังนี้

printLinkedList method
อธิบายรูปคือ printLinkedList method มีการรับพารามิเตอร์ตัวเองคือ Node head คือต้นลิสต์ เอาไว้สำหรับท่องเข้าไปยังโหนดทั้งหมดในลิสต์ แล้วแสดงค่าในโหนดต่างๆ ออกมาตามรูปแบบที่ต้องการ
  • Node trav = head; สร้างโหนด trav ขึ้นมาและกำหนดค่าให้เท่ากับ head ซึ่งชี้อยู่ที่ต้นลิสต์
  • ใน while loop ทำการท่องเข้าไปในลิสต์ที่ละโหนด แล้วแสดงค่าต่างๆ ออกมาตามรูปแบบต้องการ จะพบว่าการเข้าถึงข้อมูลในแต่ละโหนดนั้นสามารถเข้าถึงได้โดยตรงเช่นเดียวกับการกำหนดค่า และจะหยุด loop ก็ต่อเมื่อ trav ท่องไปจนสุดลิสต์
  • trav = trav.link; กำหนดให้โหนด trav ท่องไปยังโหนดถัดไป

- main method เขียนโค๊ดได้ดังนี้

main method
อธิบายรูปคือ main method จะมีการรับค่ามาจากผู้ใช้เป็นจำนวนนักเรียนที่ต้องการใส่ข้อมูล และทำการใช้ for loop วนรับค่าเก็บไว้ที่ตัวแปรตามลำดับ และเรียกใช้ method insertNode เพื่อเพิ่มโหนดใหม่ไปยังลิสต์ และมีการเรียกใช้ method linkedList เพื่อแสดงค่าทั้งหมดในลิสต์
  • Node head = null; สร้างโหนด head เพื่อเอาไว้ชี้ต้นลิสต์
  • head = insertNode(head, fName, lName, id, score); เรียกใช้ insertNode method เพื่อนำข้อมูลที่รับมาจากผู้ใช้ใส่เข้าในในโหนด และเพิ่มโหนดเข้าไปในลิสต์ และ method นี้จะรีเทิร์นค่าที่เป็น Node ที่เป็นต้นลิสต์กลับมา จึงกำหนดค่าให้กับโหนด head
  • printLinkedList(head); แสดงค่าแต่ละโหนดในลิสต์
ก็จะได้ Linked List อย่างง่ายไปใช้งาน แต่จริงๆแล้วยังมี method ที่สามารถทำได้อีกเช่น การเพิ่มข้อมูลเข้าไปที่ต้นลิสต์ การเพิ่มข้อมูลแบบเรียงลำดับ การลบข้อมูลที่ต้นลิสต์ การลบข้อมูลที่ท้ายลิสต์ การลบข้อมูลโดยอ้างอิงข้อมูลที่ตรงกับข้อมูลในสิลต์ การค้นหาข้อมูลในลิสต์ เป็นต้น

โค๊ดสมบูรณ์ของทั้งสองไฟล์สามารถดาวน์โหลดได้ดังนี้