นาฬิกา

วันอาทิตย์ที่ 10 กุมภาพันธ์ พ.ศ. 2556

พื้นฐานไมโครคอนโทรลเลอร์ด้วย Arduino


พื้นฐานไมโครคอนโทรลเลอร์ด้วย Arduino

ไมโครคอนโทรลเลอร์คืออะไร
ไมโครคอนโทรลเลอร์ คือ อุปกรณ์ที่มีหน่วยประมวลผลและความจำขนาดเล็กภายในตัวเอง สามารถรับ-ส่ง ข้อมูลได้ทั้งแบบดิจิตอลและอนาล็อก ใช้พลังงานน้อย ทำให้เป็นที่นิยมในการใช้งานในรูปแบบที่เรียกว่า Embedded เช่น เครื่องใช้ไฟ้าอัจฉริยะทั้งหลาย
Arduino คืออะไร
Arduino (อ่านว่า อา-ดู-อิ-โน่ หรือจะเรียกว่า อาดุยโน่ ก็ได้) คือ ไมโครคอนโทรลเลอร์ ชนิดหนึ่ง ซึ่งเป็นแบบที่เรียกว่า Open Hardware กล่าวคือ Arduino อุปกรณ์ที่มีแบบส่วนประกอบเป็นมาตรฐานที่เปิดเผย หมายความว่า เราสามารถทำเองโดยใช้แบบที่มีการเปิดเผยทั่วไปก็ได้ หรือสามารถซื้อหาได้ง่าย มีราคาถูก มีซ๊อพต์แวร์ให้ใช้งานฟรี สามารถนำไปใช้งานทั่วไปหรือแบบธุรกิจได้โดยไม่ต้องเสียค่าลิขสิทธิ์ เป็นรูปแบบที่มีข้อมูลมากที่สุดบนอินเตอร์เน็ต การพัฒนาก็ง่าย เพราะมีตัวอย่างมากมาย และไม่ต้องเขียนโปรแกรมในรูปแบบ Low Level หมายความว่า เราสามารถใช้คำสั่งเขียนโปรแกรมได้เสมือนโปรแกรมภาษาชั้นสูงทั่วไป

ดาวโหลดซ๊อพต์แวร์
สามารถดาวโหลดซ๊อพต์แวร์ได้ที่ http://arduino.cc/en/Main/Software โดยเราสามารถดาวโหลดได้ตาม OS ที่เราใช้ เช่น Windows, Linux หรือ Mac เมื่อดาวโหลดมาแล้ว ขอให้แตกไฟล์ไว้ในเครื่องของเรา จากนั้นให้ดับเบิ้ลคลิกไฟล์ arduino.exe (ถ้าเราใช้ Windows) ก็จะเปิดโปรแกรมดังรูป

ตัวอย่างไฟกระพริบ
โดยปกติแล้วบอร์ด Arduino ที่ซื้อมา มักจะมาพร้อมกับไฟ LED ที่ต่ออยู่กับขาหมายเลข 13 ของไมโครคอนโทรลเลอร์อยู่แล้ว ดังนั้นในตัวอย่างแรก เราจะใช้อุปกรณ์ที่มีอยู่แล้วมาใช้งาน โดยที่ไม่ต้องต่ออุปกรณ์ใดๆเลย เริ่มต้นขอให้ต่อสาย USB เข้ากับบอร์ดและต่อเข้ากับช่อง USB ในเครื่องคอมพิวเตอร์ จากนั้นให้รอจนเครื่องคอมพิวเตอร์พบอุปกรณ์ เราจะพบว่า บนเครื่องของเราจะมี Port เพิ่มขึ้นมา 1 พอร์ต ซึ่งก็คือพอร์ตที่เราจะใช้งานให้คอมพิวเตอร์คุยกับบอร์ดของคอนโทรลเลอร์นั่นเอง ในกรณีที่เครื่องคอมพิวเตอร์ไม่สามารถหาไดรเวอร์ได้ ขอให้ไปดาวโหลดไดรเวอร์ที่ http://www.ftdichip.com/FTDrivers.htm
โดยปกติแล้วบอร์ด Arduino จะต้องมีไฟเลี้ยง 5 โวลล์ แต่ถ้าเราต่อกับคอมพิวเตอร์ มันก็จะใช้ไฟเลี้ยงที่ออกจาก USB ได้เองทำให้สะดวกมาก จากนั้นขอให้เปิดโปรแกรม Arduino ขึ้นมา ไปที่เมนู Tools->Board จากนั้นให้เลือกรุ่นบอร์ดที่ตรงกับที่เราใช้งาน ในที่นี้ผมใช้ Arduino Mega ADK (หากท่านยังไม่มีสามารถซื้อได้ที่ http://www.thainetbeans.com/forum/viewtopic.php?t=1164) จากนั้นให้ไปที่เมนู Tools->Serial Port แล้วเลือกพอร์ตที่เพิ่มมาใหม่ ในกรณีที่ไม่แน่ใจ ให้ลองดึงสาย USB ที่ต่อออก แล้วลองต่อใหม่ ก็จะเห็นว่าเราใช้พอร์ตอะไรอยู่ จากนั้นให้ไปที่เมนู File->Examples->Basics->Blink หรือเขียนโปรแกรมตามนี้
void setup() {
// initialize the digital pin as an output.
// Pin 13 has an LED connected on most Arduino boards:
pinMode(13, OUTPUT);
}
void loop() {
digitalWrite(13, HIGH); // set the LED on
delay(1000); // wait for a second
digitalWrite(13, LOW); // set the LED off
delay(1000); // wait for a second
}

จากนั้นให้คลิกปุ่ม Upload บน Toolbar ดังรูป

รอสักครู่ เราจะเห็นไฟกระพิบถี่ๆ เป็นการแสดงว่าคอมพิวเตอร์กำลังส่งข้อมูลระหว่างบอร์ดอยู่ เมื่อเสร็จแล้วเราจะเห็นว่ามีไฟกระพริบเปิดและปิดทุกช่วงวินาที เราจะพบว่าตัวโปรแกรม(เราเรียกว่า sketch) นั้นมีขนาดเล็กมากและมีเพียง 2 ฟังชั่นเท่านั้น โดยฟังชั่นทั้ง2นั้น เป็นฟังชั่นพื้นฐานที่จะต้องมีเสมอ ฟังชั่น setup จะทำงานครั้งแรกเพียงครั้งเดียวหรือทุกครั้งที่เราเปิดเครื่องใหม่ ในที่นี้เราสั่งบอร์ดว่าเราจะใช้ขาที่ 13 สำหรับส่งข้อมูลออกไป ส่วนฟังชั่น loop จะทำงานวนไปตลอดไม่หยุด ในที่นี้ก็คือส่งค่าแบบดิจิตอลไปที่ขา 13 โดยมีค่าสูง(5 โวลล์) แล้วหยุดรอ 1 วินาที ทำให้ไฟ LED ติด จากนั้นจึงแบบดิจิตอลไปที่ขา 13 โดยมีค่าต่ำ(0 โวลล์) แล้วหยุดรอ 1 วินาที ทำให้ไฟ LED ดับ โดยฟังชั่น delay จะเป็นการสั่งให้บอร์ดหยุดรอโดยมีหน่วยเป็น millisecond

รวมอาการเสียของทีวี

ยี่ห้อ รุ่น อาการและวิธีการแก้ไข

central clv274 ไฟไม่เข้า clv274 มีไฟ300v แต่เครื่องไม่ทำงาน opto เสีย ic801 ,tr Q804 c2230y ใช้ c930ได้
central clv274 ไฟไมเข้า เช๊ค r 424 10k/1/2w ,r819 ประมาณค่า 10k 1/4w ,c820 10uF/160v ใช้ str s6707
conic tcn 8705 รับภาพไม่ได้ เปลี่ยนสวิสกดช่องใหม่และซ่อมลายปริ้นที่ขาดบริเวรไฟแบนด์ vl,vh,vu
contec ctv28-33avr ไม่มีเสียงภาพปกติ เปลี่ยนไอซีภาคเสียง tda2007และไดโอดไหม้

daewoo dtc1495t ไฟไม่เข้า แก้ไข kv94199
daewoo non ไฟเข้ารับภาพได้ มีสี มีเสียงไม่มีสัญญาณ เช๊ค sw201 ปกติจะอยู่ริมเช๊ค tr Q201 Tr ชนิด pnp
daewoo non ขา e จะมีไฟ 7.5v ขา b 6.9v
daewoo non ไม่มีภาพมีแต่สโนว์ วัดไฟที่ขาจูนเนอร์ vt ได้32v ส่วนขาแบน vl vh u ปกติเช๊ค Q911
daewoo non เส้นเดียวกลาง จอ วัด ic651 ,301 ,r420 ,c422 ปกติจะมีไฟ17v

distar 14" จอมืด เครื่องโดนฟ้าลง มีซีระเบิดที่แจ๊คสายอากาศ
distar 20" ช่อง 3,5ไมชัด เปลี่ยนซีไอเอฟเป็นค่า 60pและ 50pFแล้วจูนใหม่
distar 214av ไฟไม่เข้า เช๊ค ic805 มีไฟ300v ปกติวัดไฟที่ขา10 มีไฟ300v เบอร์ stk7348แต่ไม่มีไฟ114v
distar cbt ไฟเข้าจอเป็นสีเขียวหรือแดง น้ำเงิน แล้วภาพค่อยจางหายไปจนเป็นสีขาวไม่มีภาพ เช๊ค r680k 3
distar cbt ตัว 1/2w ตำแหน่ง 918,904,911 r12k 3ตัว 1w ตำแหน่ง 917,914,921
distar ct-114av ไฟเข้าแต่ไม่มีภาพ ไม่มีเสียง ลองเร่งไฟสกรีนดูว่ามีเส้นเดียวกลางจอหรือไม่ ถ้าเป็นเส้นเดียวกลาง
distar ct-114av จอให้เช๊ค ic 102 7812
distar dt-1416a ไฟเข้าเสียงปกติเป็นเส้นแหมือน ic v เสีย เปลี่ยน ic v แล้วยังเหมือนเดิม หรือถ้าวัดไฟที่ ic v
distar dt-1416a ปกติแล้ว ic ไม่เสีย เช๊ค r309 ถ้ายืดค่าจะเป็นเส้นเดียวกลางจอเช๊ค c304 รั่วหรือเสื่อมค่า
distar dt-2008n ไฟไม่เข้า เช๊ค d806 short ไม่มีไฟทั้งเครื่อง เบอร์ her155 ใช้ ru2 แทนได้
distar dt-2112 ไฟปกติ ไม่มีภาพ เมื่อเร่งไฟสกรีนเป็นเส้นเดียวกลางจอ เช๊ค d406 เช๊คไม่มีเสียง ภาคขยาย
distar dt-2112 ปกติเช๊ค sd104
distar dt-214r เปิดไม่ติด แก้ไขย้ำจุดบัคกรีใหม่
distar dt-214r จูนแล้วล๊อคไม่อยู่ เปลี่ยนซีไอเอฟเป็นค่า 68pFแล้วจูนใหม่
distar dt-214r ไฟไม่เข้าวัดไฟขาออกต้องได้100vแต่ออกประมาณ25vให้เปลี่ยน c809 2.2uF/50v
distar dt-214r ไฟไม่เข้า วัด v ได้ปกติแต่ไม่มีกระแสถ้ามีโหลดตกลงมา 0v ถ้าไม่มีไฟปกติเช๊ค c 809
distar dt-214r 2.2uF/50v ไฟ o/p ปกติ 105v แต่วัดได้ต่ำกว่า 105v ให้เปลี่ยน c809
distar dt-214r ภาพวูบ ให้ถอดมาวัดตำแหน่ง rQ401 เป็น TR
distar dt-220r ภาพวูบ เช๊ค r809 ค่า 1.5 โอห์ม r820 ค่า 30 โอห์ม
distar dt-25r จอมืด fuse 0.5a
distar dt-42 ไม่มีภาพ จอไม่มีสี เปิดไว้สักพักจะมีภาพขึ้นมาเอง เสียงปกติ เปลี่ยน c416 10/250v
distar tc-483p จอมืด เปลี่ยนฟายแบค ซีเนอร์ 5.6vและ13v และไดโอดสองตัว
distra dt-220r ไฟเข้าเป็นเส้นเดียวกลางจอ เช๊ค ic ver ไม่เสียวัดไฟภาค v ปกติ เช๊ค r309 เสีย 15k 1/2w

gold spot 20" ภาพหดทาง h เปลี่ยน ซีค่า 1uF/100v

goldstar 16d10av2 ไฟเข้ารับภาพไม่ได้ วัดไฟจูนเนอร์ปกติ วัด tr ตำแหน่ง 102 c903 ถ้าขาดเปลี่ยนไม่หายรับภาพ
goldstar 16d10av2 ไม่ได้ให้เช๊ค R530 R58 ขาดหรือยืดค่า ประมาณ 30k
goldstar ca-14a72 เส้นเดี่ยวกลางจอ ซับขา4ของic 301 ภาพสามารคขยายได้เช็ค r301 560โอห์ม
goldstar ca-14f20 ไฟออกต่ำกว่าปกติ90v แต่ไฟออกประมาณ 50v แล้วก็ตัดเป็นเสียงจี๊ด เช๊ค d824 RU2 แทน
goldstar ca-16d10 ไฟเข้า ล๊อคภาพได้แล้วก็หนี ๆ หาย ๆ เช๊ค r108 ยืดค่า 20k
goldstar cft-2505 ไฟเข้ามีแต่เม๊ดสโนว์รับภาพไม่ได้ เช๊คแผง if sterio pc board{component side} ic110 เบอร์
goldstar cft-2505 la7555 {pif/sif} vco เช๊ค L11538.0MHz 150-489U c ในกระป๋อง L มีค่า68pFเช๊คL117aft
goldstar cft-2505 ไฟเข้ารับภาพได้แต่เวลาจูนไม่ล๊อกภาพจะหนี aft ตำแหน่ง L117 ของบอร์ด pif/sif/sterio
goldstar cft-2505 board1 หลังจากนั้นใช้มิเตอร์วัดที่แรงดันของขา 4 ic1 เบอร์ m37102m8 แล้วจูน L ตำแหน่ง
goldstar cft-2505 L117 ให้แรงดันสูงสุดประมาณ 4v
goldstar non รับภาพ ไม่ได้จูนอย่างละเอียดรับได้ ถ้าสแกนหามไม่ล๊อกวิ่งผ่าน เช๊ค L508 เสีย

grundig gd-14r เปิดเงียบ เปลี่ยน ไอซี swc tda4601
grundig gd-14r nopwr เปลียน sw power ใหม่

hitachi 14-p120r ไฟ stnby ขึ้นแต่เครื่องไม่ทำงาน เปลี่ยน c753 100uF/16v
hitachi 21'' เปิดเงียบ ได้ถอดโหลดฟายแบควัดไฟมาปกติ เพราะฟายแบคซอร์ตเปลี่ยนใหม่
hitachi c14-p091 เปิดปุ๊ปแล้วตัด จอมืด เช๊ค c910 ค่า 4.7uF/160v,FBT-2434591
hitachi c14-p192 ไฟเข้ามีภาพมีเสียงแต่ภาพยืดมีเส้นกวนเต้มจอ เช็ค d621 รั่ว ic v เบอร์เดิม upc1378h เลิกผลิต
hitachi c14-p192 แทนด้วย ix7680 หรือเบอร์ la7830 โดยใส่ r 100โอห์ม และ c 0.01uF ระหว่างขา 5 และอนุกรม
hitachi c14-p192 กับ c 0.01uF และลงกราวด์ที่ขา 5 ปกติ ขา 5 ลงกราวด์อยู่แล้ว
hitachi c20 ไฟไม่เข้าเช๊ค tr903 ถ้าปกติขา c มีไฟ300v ขาb ไม่มีไฟให้ดู r918 ค่า 47k 1/2w ใส่เป็น 47k1w
hitachi c20-p721r เปิดแล้วไฟตกมีกลิ่นโยคไหม้ เปลี่ยนโยคใหม่
hitachi cpt 2131 exr จอมืด ฟายแบคเสีย
hitachi cpt-1476 ไฟเข้าภาพหดด้านข้าง เช๊ค d601 short
hitachi fujian hfc-1401b ไม่มีเสียง เปลี่ยนลำโพง และต่อมามีภาพช่องอื่นกวน ลดเอจีซีก็ใช้ได้
hitachi fujian hfc-1425b no power เปลี่ยน fuse3a และมีไดโอดภาค swc short 2 ตัว

hoshi 14" nopwr มีโยคไหม้และทรานซิสเตอร์สวิทชิ่ง เสีย

international 14" เปิดเครื่องภาพเขียวเห็นเส้นภาพปกติ เช๊คพบว่ามีซีขาหลุดที่ตำแหน่งสายอากาคและ
international 14" R120K ขาด ต่อไปไบท์เนท
international 14" เปิดเงียบ พบว่าไดโอดเร๊คติไฟชอร์ต และr ค่า 4โอห์ม5w fuse 3a
international b275 จอมืดแสงออกมาด้านข้างของจอภาพนิดนึงหรือครึ่งหนึ่งขอจอ แก้ไข วัดไฟที่ขา c ของภาค video
international b275 amp ไฟมีพอหรือไม่ปกติต้องได้ประมาณ 100v ถ้ามีไม่ถึงให้เช๊ค r,c บริเวณฟายแบค r ตำแหน่ง
international b275 c412เสีย
international kt-8188 ไม่ดัง เปลี่ยน volume ใหม่
international kt-8188 จอมืด เปลี่ยนหม้อแปลงชุด swc และเปลี่ยนซีอิเล็กทรอไลท์ตัวเล็กภาคจ่ายไฟสองตัว
international kt-8188 note { หม้อแปลงชุดสวิสชิ่งเบอร์ไม่ตรงก็ใช้ได้ให้ขาเท่ากันยี่ห้อเดียวกัน}
international p2001xxbgn ไม่มีภาพ จูนช่องไม่ได้ เปลี่ยนไอเอฟภาพ=2ตัว,เปลี่ยน r เกือกม้า agc และจูนให้ใช้ได้

jvc 21" ไม่มีเสียงภาพทาง v ม้วนขึ้น ย้ำจุดบัคกรีภาคเสียง และภาคเวอร์ใหม่
jvc 21" ภาพหดแนวตั้ง ย้ำจุดบัคกรีภาค เวอร์ใหม่
jvc av-e258 จอมืด เปลี่ยนฮอร์เอาท์เบอร์ d1878
jvc av-g219 เปิดไม่ติด ภาคฮอร์ไม่ทำงานไฟบีบวกปกติ เพราะ fet h-osc short เบอร์ bsn274
jvc c-1455 สีเพี้ยนและแตก ได้เปลี่ยนซีค่า68pFในกระป๋องไอเอฟสีแล้วจูนใหม่

lg non ฟลายแบคเสียเบอร์ 6174z-8005e ใช้ เบอร์ 154-177b ขาจะตรงกับเบอร์เดิม ถ้าใช้154-177e
lg non ขาจะไม่ตรงกัน ต้องวัดเทียบ

luxor typ1805 181m ภาพไม่ชัด แจ๊คสายอากาศหลุดมา

mitsubishi 14cz1m เปิดเครื่องมีเสียงจี๊ด ๆ มีzener ไฟบีบวกชอร์ตเบอร์ R2KY คร่อมซีไฟบีบวก 110v
mitsubishi 14cz3m ไฟเข้าภาพปกติ แต่มืดไปครึ่งจออีกครึ่งจอสว่างปกติ เช๊ค c205 470uF/16v เสีย
mitsubishi 14cz3m ไฟเข้าภาพล้มมีเสียงมีแสง เช๊ค c503 1uF/50v รั่ว
mitsubishi 20" ภาพเป็นริ้วทาง v พบว่ามี tr v o/p ลีค 1 ตัวและเปลี่ยนซี22uF/160v
mitsubishi 20cz1 เป็นเส้นแนวนอนบางครั้ง แก้ไขย้ำจุดบัคกรีใหม่
mitsubishi 20cz1m ภาพหด4ด้าน ใช้ไฟ110vจากภายนอกมีภาพปกติ r903,r904 120k ขาดหรือยืดค่า
mitsubishi 21cz1 ภาพเบลอ เปลี่ยน socket คอหลอดใหม่
mitsubishi ct-2023t ไม่ติดเปลี่ยน sw pwr และจูนไอเอฟใหม่
mitsubishi ct21am1 มีแต่ไฟ stby ปุ่มควบคุมต่าง ๆ ใช้ไม่ได้ d206,d606 ic tda8361ใช้ tda8362แทน
mitsubishi non ไฟเข้าเป็นเส้นเดียวกลางจอ เปลี่ยน ic v ตำแหน่ง401 เบอร์an5515 แล้วภาพยังไม่ขยายวัดไฟ
mitsubishi non ได้ปกติเอามือจับขา4 ภาพจะขยายวูบวาบเช๊ค ic201 เบอร์ tda8361
mitsubishi ss10/ss1 ภาพจางมากออกจะมืดเล็กน้อยปรับสกรีนขึ้นลงได้ปรับโฟกัสไม่ดีขั้นเหมือนซ๊อคเก๊ตหลอดภ
าพ
mitsubishi ss10/ss1 เสียมีเสียงตามรายการทีวีชัดเจน ถ้าลดไบร์ทให้หมดจะเห็นภาพจาง ๆ ให้วัดไฟที่ ic201 ขาที่25
mitsubishi ss10/ss1 ปกติจะมีไฟประมาณ 5.3vถ้ามีไฟน้อยประมาณ6vให้ลองวัด vr202 ขากลางต้องมีไฟประมาณ
mitsubishi ss10/ss1 6-11v ถ้าจุดนี้ปกติให้เช๊ควงจร abL เช๊ค r 55 ค่า 270k


http://tvclub.thaimeboard.com/index.php?topic=21.0

วันศุกร์ที่ 8 กุมภาพันธ์ พ.ศ. 2556

พระบาทสมเด็จพระเจ้าอยู่หัว ทรงพระราชทานประทับรอยพระบาทในวันที่ 27 ก.พ. 2525

พระบาทสมเด็จพระเจ้าอยู่หัว ทรงพระราชทานประทับรอยพระบาทในวันที่ 27 ก.พ. 2525
       หลายต่อหลายครั้งที่ขึ้นเหนือไปแอ่วเชียงราย ผมเคยเจอทั้งการ “หลงทาง” และ “หลงเธอ” แถมบางครั้งยังหลงเธอจนทำให้หลงทางอีกต่างหาก
     
       แต่ถ้าหากบอกว่า“หลงถัง”นี่ ผมไม่คุ้นกับชื่อนี้เลยจริงๆพับผ่าสิ
     
       ดอยพญาพิภักดิ์ 
     
       หลงถังคือชื่อของ “ภูหลงถัง” แหล่งท่องเที่ยวเปิดใหม่ของจังหวัดเชียงราย ซึ่งทางททท.เชียงราย ได้ชูกิจกรรม“เที่ยวสามภู ในหนึ่งวัน”ขึ้น ด้วยการนำเสนอเส้นทางท่องเที่ยวเชื่อมโยง ระหว่าง ภูชี้ฟ้า-ภูผาตั้งหรือดอยผาตั้ง และภูหลงถัง ที่ตั้งอยู่ ณ ต.ยางฮอม อ.ขุนตาล(อดีตอยู่ใน อ.เทิง)
พสกนิกรมาเฝ้ารอรับเสด็จฯในหลวงที่ดอยพญาพิภักดิ์
       หลงถังเป็นชื่อเก่าดั้งเดิมของ“ดอยพญาพิภักดิ์” ดอยที่มีชื่อมาจากชื่อของหมู่บ้านพญาพิภักดิ์ หมู่บ้านเก่าแก่ของชุมชนชาวม้งที่มี “พญาพิภักดิ์” หรือ “ปะตุ๊ แซ่ย้ง”(ชาวม้ง)เป็นหัวหน้าชุมชน
     
       ดอยพญาพิภักดิ์นับเป็นสถานที่ที่มีความสำคัญทางประวัติศาสตร์แห่งหนึ่งของจังหวัดเชียงราย เนื่องจากในยุคสงครามเย็นที่มีการรบพุ่งกันระหว่างรัฐบาล(ทหาร)ไทยกับกลุ่มผู้ฝักใฝ่ในลัทธิคอมมิวนิสต์(พรรคคอมมิวนิสต์แห่งประเทศไทย-พคท.) และชาวบ้านในพื้นที่ที่หลายๆคนไม่รู้อิโหน่อิเหน่ แต่กลับถูกเจ้าหน้าที่รัฐผลักไสให้ไปอยู่ฝ่ายตรงข้าม ในพื้นที่ดอยยาว-ดอยผาหม่น บนดอยพญาพิภักดิ์ ถือเป็นจุดยุทธศาสตร์สำคัญ เป็นพื้นที่สีแดง(คนละแดงกับปัจจุบัน)ซึ่งทางรัฐบาลได้ส่งกองกำลังเข้ามาตั้งแต่ปี พ.ศ. 2510 จนเกิดเสียงปืนแตกนำสู่การต่อสู้ที่ยืดเยื้อขึ้น
     
       จนกระทั่งในปี พ.ศ. 2524 พันโทวิโรจน์ ทองมิตร ผู้บังคับกองพันทหารราบที่ 473 ได้นำกำลังพลเข้าปฏิบัติการในยุทธการยึดเนิน 1188 บนดอยพญาพิภักดิ์ จนสามารถปราบปรามคอมมิวนิสต์ในพื้นที่นั้นลงได้
     
       แต่การสู้รบครั้งนั้น เหล่าทหารหาญก็ได้พลีชีพเพื่อชาติไปเป็นจำนวนมาก ดังนั้นเพื่อเป็นขวัญกำลังใจแก่เหล่าทหารหาญ พระบาทสมเด็จพระเจ้าอยู่หัวฯ พร้อมด้วยสมเด็จพระนางเจ้าพระบรมราชินีนาถฯ สมเด็จพระเทพรัตนราชสุดาฯ และพระเจ้าวรวงศ์เธอพระองค์เจ้าโสมสวลีฯ ได้เสด็จฯไปเยี่ยมเยียนเหล่าทหารหาญและพสกนิกรแล้ว ณ ฐานปฏิบัติการพญาพิภักดิ์ บนดอยยาว ท่ามกลางหมู่ชาวบ้านที่เดินทางมาเฝ้ารอรับเสด็จฯเป็นจำนวนมาก ในวันที่ 27 กุมภาพันธ์ พ.ศ. 2525
รอยพระบาทในหลวง ที่ประดิษฐานอยู่ ณ ค่ายเม็งรายมหาราช
       นอกจากนี้ในการเสด็จฯครั้งนั้นพระเจ้าอยู่หัวฯ ยังได้ทรงพระกรุณาโปรดเกล้าฯพระราชทานประทับรอยพระบาทของพระองค์ลงบนแผ่นปูนปลาสเตอร์ที่ทางทหารได้จัดเตรียมไว้ ตามคำกราบบังคมทูลของพันโทวิโรจน์ ที่ศาลาบนดอยพญาพิภักดิ์
     
       ในเรื่องนี้ทหารที่อยู่ในเหตุการณ์ครั้งนั้นได้บันทึกเอาไว้ว่า(คัดลอกจากหนังสือ “เที่ยวตามพ่อ” สนพ.อัศเจรีย์)
     
       ...เมื่อพระองค์ท่านถอดรองพระบาท(รองเท้า)ได้เผยให้เห็นถึงถุงพระบาทที่ขาด ก่อนจะถอดถุงพระบาท และได้ประทับพระบาทลงในเบ้าพิมพ์ที่เป็นปูนปลาสเตอร์ผสมหมาดๆ 
     
       ถุงพระบาทนั้น คือสิ่งที่ได้แสดงให้เห็นว่า พระองค์คือ ทรงเป็นทั้งนักทฤษฎีและปฏิบัติ พระองค์น่าจะมิใช้พระมหากษัตริย์ซึ่งทรงครองสิริราชสมบัติยาวนานแต่เพียงสถานเดียว แต่ทรงเป็นพระมหากษัตริย์ที่ทรงปฏิบัติพระองค์อย่างเรียบง่าย สมถะ รู้จักคุณค่าของการใช้ สิ่งของมากยิ่งกว่าพระมหากษัตริย์ใดในโลก หรือยิ่งกว่าสามัญชนแม้กระทั่งพสกนิกรมากหลายที่ยังดำเนินชีวิตอย่างถูกต้องมีความพอเพียงเช่นนั้นไม่ได้...
     
       นอกจากนี้ในการเสด็จฯครั้งนั้น แม้สถานการณ์ควันไฟจากการสู้รบจะเพิ่งสงบได้หมาดๆ ยังคงสุ่มเสี่ยงต่อภยันอันตราย เพราะในเขตพื้นที่ดอยพญาพิภักดิ์(เขตงานที่ 8)ถือเป็นหนึ่งในเขตที่มีความรุนแรงที่สุด เพราะเป็นประตูในปฏิบัติการประสานกันระหว่างพรรคคอมมิวนิสต์ในไทย ลาว และ เวียดนาม แต่ด้วยน้ำพระทัยอันกล้าหาญพระบาทสมเด็จพระเจ้าอยู่หัวฯ พระองค์ท่านทรงรับการมอบตัวและมอบอาวุธต่อกองกำลังฝ่ายตรงข้ามกับรัฐบาลเพื่อรับเข้าเป็นผู้ร่วมพัฒนาชาติไทย ทำให้ความขัดแย้งยุติลง ความสงบสันติสุขกลับคืนมา
ในวันฟ้าเปิด ณ ลานชมวิว ภูหลงถังสามารถมองเห็นภูชี้ฟ้า(ยอดแหลม)ได้อย่างชัดเจน
       สำหรับการมอบอาวุธครั้งนั้น หนึ่งในผู้ที่ออกจากป่ามาเข้าร่วมเป็นผู้พัฒนาชาติไทยก็คือ “สหายด้วย” หรือชัยยุทธ อนุสรณ์ศิลปะ ชาวไทยภูเขาเผ่าม้งที่ปัจจุบันดำรงตำแหน่งผู้ใหญ่บ้านหรือพ่อหลวงแห่ง ม.13 ต.ยางฮอม
     
       สหายด้วยรำลึกความหลังเมื่อครั้งออกจากป่าให้ผมฟังด้วยความซาบซึ้งว่า เป็นเพราะพระบารมีของในหลวงที่ทรงมายุติความขัดแย้ง จึงทำให้เขาได้ออกจากป่ามาใช้ชีวิตตามปกติ นับเป็นพระมหากรุณาอันล้นพ้น
     
       ภูหลงถัง 
     
       หลังเหตุการณ์สงบ ดอยพญาพิภักดิ์ก็ได้รับการพัฒนาเรื่อยมา และด้วยสภาพพื้นที่ที่ตั้งอยู่บนเทือกเขาสูงเหนือระดับน้ำทะเลเฉลี่ย 1,200 เมตร ทำให้ดอยพญาพิภักดิ์ที่ตอนหลังนิยมเรียกขานอีกชื่อหนึ่งว่า“ภูหลงถัง” ได้รับการพัฒนาให้เป็นแหล่งท่องเที่ยวแห่งใหม่ของจังหวัดเชียงราย
     
       บนยอดภูแห่งนี้น่ายลไปด้วยวิวทิวทัศน์อันงดงาม โดยเฉพาะบนลานชมวิวในวันที่ฟ้าเปิดสามารถมองเห็นวิวทิวทัศน์เบื้องล่างได้อย่างกว้างไกล อีกทั้งยังสามารถมองไปเห็นยอดแหลมๆที่ชี้ขึ้นไปทิ่มแทงฟ้าของภูชี้ฟ้าได้อย่างชัดเจนอีกด้วย
สระมังกร
       ขณะที่จุดท่องเที่ยวสำคัญอีกแห่งหนึ่งของภูแห่งนี้ก็คือ “สระมังกร” ที่เป็นตาน้ำผุดตามธรรมชาติบนยอดเขาจนเกิดเป็นสระน้ำขนาดย่อมขึ้นมา
     
       สระมังกรแห่งนี้เป็นที่มาของชื่อภูหลงถัง(ที่ถือเป็นสิ่งคาใจผมนับตั้งแต่ได้ยินชื่อนี้ครั้งแรก) ซึ่งสหายด้วยได้ไขความกระจ่างให้ผมฟังว่า ในยุคที่มีการสู้รบทางกองกำลังชาวทหารจีนคณะชาติ(กองพล 93) ที่อพยพเข้ามาอยู่แถบทางภาคเหนือของเมืองไทยได้นำกำลังพลเข้ามาร่วมรบกับรัฐบาลไทย แล้วเห็นว่าที่นี่มีสระน้ำที่เกิดจากตาน้ำผุดตามธรรมชาติ จึงตั้งชื่อตามความเชื่อแบบคนจีนว่า“หลงถัง”ที่หมายถึง “สระมังกร” อันเป็นที่มาของชื่อภูหลงถังดังในปัจจุบัน
ศาลาประทับรอยพระบาท วนอุทยานพญาพิภักดิ์
       นอกจากลานชมวิวและสระมังกรแล้วบนภูหลงถังยังมี แปลงไร่กุหลาบ สวนกาแฟ วิถีชีวิตวัฒนธรรม และหมู่บ้านประวัติศาสตร์ให้สัมผัสเที่ยวชมกัน รวมไปถึง “วนอุทยานพญาพิภักดิ์” ที่ถือเป็นอีกหนึ่งสถานที่ไฮไลท์สำคัญของภูแห่งนี้
     
       วนอุทยานพญาพิภักดิ์ เป็นสถานที่ที่ในหลวงเคยเสด็จมาพระราชทานประทับรอยพระบาทที่ดอยพญาพิภักดิ์แห่งนี้ ซึ่งชาวบ้านที่นี่ยังได้เรียกขานรอยพระบาทของพ่อหลวงในอีกชื่อหนึ่งว่า “รอยพระบาทแห่งสันติสุข
     
       สำหรับรอยพระบาทในหลวงที่ประทับ ณ ดอยพญาพิภักดิ์นั้น มี 2 รอยด้วยกัน รอยแรก เกิดจากการประทับรอยครั้งแรก เป็นรอยที่ประทับไม่สมบูรณ์ เพราะปูนมีน้ำมากเกินไป ถูกนำไปเก็บไว้กับครอบครัวหนึ่งในจังหวัดเชียงใหม่ ส่วนอีกรอย เป็นการประทับครั้งที่สอง เป็นรอยที่สมบูรณ์ ปัจจุบันประดิษฐานอยู่ที่ศาลารอยพระบาท ค่ายเม็งรายมหาราช อ.เมือง จ.เชียงราย
ภาพถ่ายรอยพระบาทในศาลาประทับรอยพระบาท
       แต่...นับเป็นที่น่าเสียดายยิ่งที่ “ศาลาประทับรอยพระบาท” บนวนอุทยานพญาพิภักดิ์ ไม่มีรอยจริงให้สักการะสักรอย มีแต่จุดที่ในหลวงเสด็จมาประทับรอยพระบาทที่มีการปลูกต้นไม้ล้อมรอบไว้ กับภาพถ่ายรอยพระบาทให้ยลเท่านั้น ซึ่งที่ผ่านมาชาวบ้านที่นี่ภายใต้การนำของสหายด้วยได้พยายามที่จะไปยื่นหนังสือทำเรื่องขอคืนรอยพระบาทรอยแรกยังบ้านที่นำไปเก็บไว้เป็นสมบัติส่วนตัว แต่สุดท้ายสหายด้วยกับโดนแจ้งความในข้อหาบุกรุกเสียนี่
     
       อย่างไรก็ตามกับเรื่องนี้ได้มีผู้แนะนำว่า ทางจังหวัดเชียงรายควรทำจดหมายถึงทางสำนักพระราชวังเพื่อขอพระราชทานพระบรมราชานุญาตหล่อรอยพระบาทในหลวงจำลองขึ้นมาใหม่ ที่หากสามารถทำได้ก็ถือเป็นการหาทางออกที่ดีทีเดียว เพราะรอยพระบาทในหลวงถือเป็นสิ่งที่มีคุณค่าทางจิตใจของชาวบ้านที่นี่ อีกทั้งนี่ยังเป็นจุดดึงดูดให้ผู้คนขึ้นมาสักการะเที่ยวชมรอยพระบาทในหลวง(เสมือนจริง)ในสถานที่จริงอีกด้วย
ส่วนหนึ่งของผืนป่าที่ชาวบ้านอนุรักษ์ไว้ท่ามกลางบริเวณรอบข้างที่โดนแผ้วถาง
       นอกจากรอยพระบาทในหลวงแล้ว อีกสิ่งหนึ่งที่ถือเป็นการแสดงถึงความเคารพเทิดทูนต่อในหลวงแบบเป็นรูปธรรมของบ้านที่นี่ก็คือ “ป่าในหลวง
     
       สหายด้วยบอกกับผมว่า เมื่อครั้งที่ในหลวงเสด็จมาประทับรอยพระบาทบนดอยพญาพิภักดิ์ พระองค์ท่านได้ผินพระพักตร์ไปทางทิศตะวันตก แล้วตรัสว่า “นี่คือป่าของฉัน
     
       นับแต่นั้นมาชาวบ้านก็ช่วยกันดูแลรักษาพื้นป่าแห่งนี้ไว้ให้มีสภาพอุดมสมบูรณ์ มากไปด้วยพืชพรรณไม้ กล้วยไม้ป่า นกนานาชนิด ที่ชาวบ้านที่นี่เขาวางแผนว่าในอนาคตถ้ามีความพร้อม พวกเขาจะเปิดเส้นทางท่องเที่ยวเรียนรู้ ศึกษาธรรมชาติ ในผืนป่าในหลวงเพิ่มอีกจุดหนึ่ง
     
       สำหรับป่าในหลวงเท่าที่ผมไปสัมผัสมาที่นี่เปรียบดังโอเอซิสสีเขียวของชุมชนทีเดียว เพราะในขณะที่บริเวณรอบข้างถูกพักล้างถางพงแต่ผืนป่าแห่งนี้กลับยังคงสภาพร่มรื่นเขียวครึ้ม นับเป็นผืนป่าใต้พระบารมีของพ่อหลวงอย่างแท้จริง
จุดประทับรอยพระบาทของในหลวง
       และนี่ก็คือเรื่องราวบางส่วนของภูหลงถังที่แม้หลายสิ่งหลายอย่างอาจจะยังดูขาดตกบกพร่อง ไม่ลงตัวเข้าที่เข้าทาง เพราะนี่เพิ่งเปิดตัวเป็นแหล่งท่องเที่ยวใหม่เอี่ยม ชาวบ้านยังไม่มีประสบการณ์ แต่พวกเขาก็มีความตั้งใจและมีความหวังในการที่จะพัฒนาชุมชนของพวกเขาในน่าอยู่น่าเที่ยวยิ่งขึ้น
     
       ที่สำคัญคือการขึ้นมาแอ่วที่นี่มันทำให้ผมได้สัมผัสกับการแสดงออกถึงความเคารพเทิดทูนและซาบซึ้งในพระมหากรุณาธิคุณของพระบาทสมเด็จพระเจ้าอยู่หัว ซึ่งเมื่อเห็นแล้วผมอดนึกถึงคนกลุ่มหนึ่งในบ้านเราไม่ได้
     
       คนกลุ่มนี้นิยมสร้างวาทะกรรมสวยหรู อ้างสิทธิเสรีภาพ อ้างประชาธิปไตย อ้างเมืองนอก อ้างความเป็นวิชาการ เพื่อให้ตัวเองดูดี แต่ในความเป็นจริงสิ่งที่พวกเขาแสดงออกมาต่อสาธารณะชนคนไทยส่วนใหญ่(ยกเว้นในกลุ่มพวกเขาที่ยกหางกันเอง) กลับเต็มไปด้วยอีโก้ที่ทะลักทะล้น(รูทวาร)
     
       คนกลุ่มนี้แม้หลายคนจะดูเปลือกนอกมีสถานะทางสังคมที่ดีกว่าชาวบ้านที่นี่ แต่ก็ไม่รู้ว่าผีห่าซาตานอะไรดลใจให้พวกเขามีความตรรกะที่บิดเบี้ยวและมีความคิดหลงทางจนสุดกู่
      
       สุดกู่ถึงขนาดกล้าเนรคุณต่อแผ่นดินตัวเองได้
      
        

รีเลย์


รีเลย์เป็นอุปกรณ์ที่นิยมนำมาทำเป็นสวิตช์ทางด้านอิเล็กทรอนิกส์ โดยจะต้องป้อนกระแสไฟฟ้าให้ไหลผ่านขดลวดจำนวนหนึ่ง เพื่อนำไปควบคุมวงจรกำลังงานสูง ๆ ที่ต่ออยู่กับหน้าสัมผัสหรือคอนแทกต์ของรีเลย์ รูปที่ 9.1 แสดงรูปร่างและสัญลักษณ์ของรีเลย์ 
หลักการทำงานเบื้องต้นของรีเลย์แสดงดังรูปที่ 9.2 การทำงานเริ่มจากปิดสวิตช์ เพื่อป้อนกระแสให้กับขดลวด (Coil) โดยทั่วไปจะเป็นขดลวดพันรอบแกนเหล็ก ทำให้เกิดสนามแม่เหล็กไปดูดเหล็กอ่อนที่เรียกว่าอาร์เมเจอร์ (Armature) ให้ต่ำลงมา ที่ปลายของอาร์เมเจอร์ด้านหนึ่งมักยึดติดกับสปริง (Spring) และปลายอีกด้านหนึ่งยึดติดกับหน้าสัมผัส (Contacts) การเคลื่อนที่อาร์เมเจอร์ จึงเป็นการควบคุมการเคลื่อนที่ของหน้าสัมผัส ให้แยกจากหรือแตะกับหน้าสัมผัสอีกอันหนึ่งซึ่งยึดติดอยู่กับที่  เมื่อเปิดสวิตช์อาร์เมเจอร์ ก็จะกลับสู่ตำแหน่งเดิม เราสามารถนำหลักการนี้ไปควบคุมโหลด (Load) หรือวงจรอิเล็กทรอนิกส์ต่าง ๆ ได้ตามต้องการ
หน้าสัมผัสของรีเลย์
รูปที่ 9.2 แสดงรีเลย์ที่มีหน้าสัมผัสเพียงชุดเดียว ปัจจุบันรีเลย์ที่มีขดลวดชุดเดียวสามารถควบคุมหน้าสัมผัสได้หลายชุดดังรูปที่ 9.3 อาร์เมเจอร์อันเดียวถูกยึดอยู่กับหน้าสัมผัสที่เคลื่อนที่ได้ 4 ชุด ดังนั้นรีเลย์ตัวนี้จึงสามารถควบคุมการแตะหรือจากกันของหน้าสัมผัสได้ถึง 4 ชุด
แต่ละหน้าสัมผัสที่เคลื่อนที่ได้มีชื่อเรียกว่าขั้ว (Pole) รีเลย์ในรูปที่ 9.3 มี 4 ขั้ว จึงเรียกหน้าสัมผัสแบบนี้ว่าเป็นแบบ 4PST (Four Pole Single Throw) ถ้าแต่ละขั้วที่เคลื่อนที่แล้วแยกจากหน้าสัมผัสอันหนึ่งไปแตะกับหน้าสัมผัสอีกอันหนึ่งเหมือนกับสวิตช์โยก โดยเป็นการเลือกหน้าสัมผัส ที่ขนาบอยู่ทั้งสองด้านดังรูปที่ 9.4 หน้าสัมผัสแบบนี้มีชื่อว่า SPDT  (Single Pole Double Throw)
ในกรณีที่ไม่มีการป้อนกระแสไฟฟ้าเข้าขดลวดของรีเลย์ สภาวะ NO (Normally Open) คือสภาวะปกติหน้าสัมผัสกับขั้วแยกจากกัน ถ้าต้องการให้สัมผัสกันจะต้องป้อนกระแสไฟฟ้าเข้าขดลวด ส่วนสภาวะ NC (Normally Closed) คือสภาวะปกติหน้าสัมผัสกับขั้วสัมผัสกัน ถ้าต้องการให้แยกกันจะต้องป้อนกระแสไฟฟ้าเข้าขดลวด นอกจากนี้ยังมีแบบแยกก่อนแล้วสัมผัส (Break-Make) หมายถึงหน้าสัมผัสระหว่าง 1 และ 2 จะแยกจากกันก่อนที่หน้าสัมผัส 1 และ 3 จะสัมผัสกัน แต่ถ้าหากตรงข้ามกันคือ หน้าสัมผัส 1 และ 2 จะสัมผัสกัน และจะไม่แยกจากกัน จนกว่าหน้าสัมผัส 1 และ 3 จะสัมผัสกัน (Make-Break)
ชนิดของรีเลย์
รีเลย์ที่ผลิตในปัจจุบันมีอยู่มากมายหลายชนิด ผู้เรียบเรียงจะขอแนะนำรีเลย์ที่นิยมใช้งานและรู้จักกันแพร่หลาย 4 ชนิดเพื่อเป็นแนวทางในการศึกษา ในระดับสูงต่อไป
  1. อาร์เมเจอร์รีเลย์ (Armature Relay)
  2. รีดรีเลย์ (Reed Relay)
  3. รีดสวิตช์ (Reed Switch)
  4. โซลิดสเตตรีเลย์ (Solid-State Relay)
1. อาร์เมเจอร์ (Armature Relay) คือรีเลย์ที่ได้อธิบายหลักการทำงานดังในรูปที่ 9.6  ซึ่งเป็นรีเลย์ที่นิยมใช้กันมากที่สุด  บางครั้งเรียกรีเลย์แบบนี้ว่า รีเลย์ชนิดแคลปเปอร์ (Clapper Relay)
2. รีดรีเลย์ (Reed Relay) เป็นรีเลย์ไฟฟ้าที่มีลักษณะเป็นแคปซูลขนาดเล็ก ในรูปที่ 9.7 แสดงภาพตัดขวางของรีเลย์ ที่ประกอบด้วยส่วนที่เรียกว่ารีดแคปซูล ซึ่งมีคอยล์พันบนแกนบ๊อบบิ้น รีดแคปซูลจะเป็นหลอดแก้ว ภายในบรรจุก๊าชเฉื่อย หน้าสัมผัสเป็นโลหะผสมแผ่นบาง ๆ ปลายตัด 2 แผ่น วางซ้อนแต่ไม่สัมผัสกัน เป็นสวิตช์ชุดเดียวทางเดียวหน้าสัมผัสปกติเปิดวงจร (SPST-NO)
3. รีดสวิตช์ (Reed Switch) เป็นรีเลย์อีกชนิดหนึ่งแต่ไม่มีชุดขดลวดสำหรับสร้างสนามแม่เหล็ก การควบคุมการปิดเปิดหน้าสัมผัส ของสวิตช์จะใช้สนามแม่เหล็กจากภายนอกมาควบคุม หน้าสัมผัส โครงสร้างภายในของรีดสวิตช์แสดงดังรูปที่ 9.8
4. โซลิดสเตตรีเลย์ (Solid-State Relay) เป็นรีเลย์ที่ไม่มีโครงสร้างทางกลอยู่ภายใน มีขั้วต่ออย่างละ 2 ขั้ว ขั้วอินพุต เป็นขั้วสำหรับป้อนสัญญาณควบคุม เพื่อบังคับให้ขั้วเอาต์พุตปิดหรือเปิดวงจร โดยจะมีการแยกกันทางไฟฟ้าระหว่างขั้วอินพุตและเอาต์พุต
การเลือกซื้อรีเลย์
การเลือกซื้อรีเลย์มีหลักที่ควรพิจารณาในการเลือกซื้อ โดยให้ระบุความต้องการเป็นข้อ ๆ ว่ารีเลย์ที่กำลังจะซื้อสามารถที่จะสนองความต้องการทั้ง 9 ข้อดังนี้
1. กระแสไฟฟ้าที่ใช้ป้อนให้กับขดลวดเป็นไฟตรงหรือไฟสลับ
2. แรงเคลื่อนและความถี่ของไฟฟ้าที่จะใช้กับขดลวดของรีเลย์
3. ความต้านทานของขดลวดมีค่าเท่าใด
4. อุณหภูมิสูงสุดเท่าใด
5. หน้าสัมผัสต้องใช้กับแรงเคลื่อนและกระแสเท่าใด
6. หน้าสัมผัสเป็นแบบใด
7. แหล่งจ่ายไฟฟ้าที่ใช้มีช่วงแรงดันเปลี่ยนแปลงไปมากน้อยเพียงใด
8. ต้องการเวลาสัมผัสและจากของหน้าสัมผัสเร็วหรือช้าเพียงใด
9. ลักษณะรูปร่างภายนอกเป็นอย่างไร และจะติดตั้งเข้ากับวงจรอย่างไร
การตรวจสอบรีเลย์
การตรวจสอบรีเลย์ว่าอยู่ในสภาพดีหรือชำรุดนั้น สามารถกระทำได้โดยใช้มัลติมิเตอร์ตั้งย่านวัดโอห์มแล้วใช้สายวัดทั้งสองสัมผัสที่ขั้วขดลวด (Coil) ของรีเลย์ทั้งสองขั้ว ถ้าเข็มมิเตอร์เบี่ยงเบนแสดงค่าความต้านทานแสดงว่ารีเลย์อยู่ในสภาพที่ใช้งานได้ แต่ถ้าหากเข็มไม่ขึ้น แสดงว่าไม่สามารถใช้งานได้
การประยุกต์ใช้งานรีเลย์
ปัจจุบันได้มีการนำรีเลย์ไปใช้ในการทำเป็นสวิตช์ทางด้านอิเล็กทรอนิกส์ในวงจรต่าง ๆ มากมาย ผู้เรียบเรียงจะขอยกตัวอย่าง รายละเอียดและรูปวงจรที่พอเป็นแนวทางในการศึกษาค้นคว้าต่อไปดังนี้
     รูปที่ 9.12 เป็นการนำรีเลย์ที่มีหน้าสัมผัส 2 ชุดมาต่อเป็นวงจรกันขโมย โดยที่หน้าสัมผัสของสวิตช์ใช้แบบปกติเปิดวงจร (NO) เมื่อมีการกดสวิตช์ S1 , S2  และ S3 ตัวใดตัวหนึ่งจะทำให้ออดส่งเสียงเตือนค้าง โดยมีสวิตช์ S4 ทำหน้าที่รีเซตวงจร
     รูปที่ 9.13 แสดงการนำรีเลย์มาต่อเป็นวงจรออสซิลเลเตอร์เพื่อทำเป็นไฟกระพริบ ภายในวงจรใช้รีเลย์ขนาด 12 โวลท์ โดยที่หน้าสัมผัสจะจากกันเมื่อแรงดันต่ำกว่า 5โวลท์ การทำงานของ วงจรเริ่มจากการกดสวิตช์ S1 จะทำให้มีกระแสไหลครบวงจรผ่านขดลวดของรีเลย์ พร้อมทั้งชาร์จไฟเข้าที่ตัวเก็บประจุ C1 ซึ่งจะทำการประจุกระแส จนกระทั่งแรงดันตกคร่อมขดลวดของรีเลย์ RY1 ทำงาน ทำให้หน้าสัมผัสแบบ NC เปิดวงจรออก ตัวเก็บประจุ C1 หยุดการชาร์จ ในขณะเดียวกันก็จะทำให้หน้าสัมผัสซึ่งเป็นแบบ NO ปิดวงจรส่งผลให้หลอดไฟ L1 สว่าง ขณะนี้ตัวเก็บประจุ C1 เริ่มคายประจุให้กับขดลวดแทน มีผลทำให้รีเลย์คงสภาวะการทำงานค้างไว้  จนกระทั่งแรงดันที่คายออกจาก C1 ค่อย ๆ ลดลงจนถึงค่าที่ทำให้ขดลวดไม่สามารถดูดหน้าสัมผัสให้อยู่ได้ จึงทำให้รีเลย์กลับสู่สภาวะเริ่มต้นหรือสภาวะปกติอีกครั้ง ทำให้หน้าสัมผัสของรีเลย์เปิดปิดสลับกันไปตลอดทำให้ไฟติดและดับสลับกัน
     รูปที่ 9.14 แสดงการนำรีดสวิตช์ไปใช้ในวงจรกันขโมย โดยฝังสวิตช์ไว้ในกรอบประตูและฝังแม่เหล็กในบานประตู ขณะที่มีการเปิดประตูจะทำให้หน้าสัมผัสของรีดสวิตช์เปิดออกตามลักษณะการเปิดปิดประตู ถ้ามีขโมยเข้ามาก็จะทราบได้ทันที

เสาอากาศสลิมจิม

เสาอากาศสลิมจิมSlim-jim ANTENNA
สายอากาศที่นำเสนอนี้เป็นสายอากาศที่มีคุณภาพดีอีกเสาหนึ่ง และเป็นที่รู้จักดีสร้างง่ายสามารถใช้งานได้เป็นเลิศ
   เสาอากาศสลิมจิม ได้รับความยินยอมเป็นอย่างมากในประเทศเรา เป็นสายอากาศที่ส่งได้ไกล เคยมีผู้ทอดลองส่งจากกรุงเทพถึงชะอำได้ และบางท่านส่งจากจังหวัดกาญจนบุรีถึงกรุงเทพได้
   การทำเสาอากาศสลิมจิมมีวิธีทำที่แตกต่างกันออกไป หลายท่านอาจนำมาต่อกันตามตัวอย่าง

    เมื่อต้องการทำเสาอากาศสลิมจิมใช้ต้องทราบก่อนว่าเราจะใช้ความถี่ในย่านความถี่ที่ต้องการเท่าไร คือความถี่ที่เราใช้ประจำ เราก็ยึดหลักและนำมาใช้ได้เลย ออกแบบให้แล้วตามรูป ตั้งแต่ย่านกระจายเสียงและย่านสมัครเล่นถึงส่วนราชการทั่วไป ส่วนรูป(D)เป็นการแสดงการใช้เข็มขัดที่รัดท่อน้ำที่เป็นโลหะใช้รัดระหว่างเสากับท่อพีวีซียาว50-70เซนติเมตรเพื่อไม่ให้สายอากาศติดกับเสาในระหว่างใช้งาน
   การปรับแต่งก็เหมือนกับการปรับเสาอากาศทั่วไปโดยเลื่อนจุดต่อขึ้นลงให้ได้ค่าSWR


   ที่นิยมทำใช้จะดัดเป็นรูปตัว(C) เทคนิคการดัดท่ออลูมิเนียมมีวิธีหลายอย่าง ถ้าจะทำให้สวยงามควรหาสปริงที่มีความยาว 8-10 นิ้วที่สามารถงอได้และติดกันตลอด เอาอลูมิเนียมที่ต้องการดัดใส่ภายในสปริงและดัดเมื่อได้ดังรูปแล้วค่อยหมุนสปริงออก หากจะไปให้ร้านที่เค้าทำแอร์ดัดท่อก็ได้สวยงามกว่ามือและหักพับง่าย ควรใช้ท่ออลูมิเนียมที่มีความใหญ่พอสมควร ส่วนมากจะใช้ประมาณ 1เซนติเมตรดูสวยงามและง่ายแก่การคำนวณ


ขอบคุณข้อมูลดีๆจากเว็บ

วันพฤหัสบดีที่ 7 กุมภาพันธ์ พ.ศ. 2556

พื้นฐานโปรแกรมภาษา C


พื้นฐานโปรแกรมภาษา C
ดร. จันทร์จิรา สินทนะโยธิน, วิศรุต พลสิทธิ สำนักงานพัฒนาวิทยาศาสตร์และเทคโนโลยีแห่งชาติ (สวทช)ฝึกฝนและพัฒนาการเขียนโปรแกรมภาษา C Introduction to C Programming การพัฒนาโปรแกรมคอมพิวเตอร์ บางคนก็ว่ายาก บางคนก็ว่าเป็นเรื่องสนุก หลายคนบอกว่า ขอเป็นแค่ผู้ใช้สนุกที่สุด แต่จะมีซักกี่คนที่จะมีใจรักที่จะก้าวไปบนถนนแห่งการพัฒนาฝีมือและฝึกฝนการเขียนโปรแกรมด้วยตัวเอง เพื่อให้มีผู้ที่สนใจนำไปใช้งาน และเพิ่มประสิทธิ์ภาพในการทำงาน และ ความสะดวกสบายๆ ต่างๆมากขึ้น ว่าไปแล้วนักโปรแกรมเมอร์เหล่านี้ ก็ไม่แตกต่างจากผู้ที่ปิดทองหลังพระมากนัก เพราะหลายๆ โปรแกรมที่มีให้ใช้งานกันในปัจจุบัน จะมีใครทราบบ้างไหมว่า ผู้เขียนโปรแกรมเหล่านั้นมีใครกันบ้าง ดังนั้น ผู้ที่คิดจะก้าวมาเป็นนักพัฒนาโปรแกรมมืออาชีพ คงต้องอาศัยใจรักที่จะอยากจะพัฒนา และฝึกฝนฝืมือในการเป็นโปรแกมเมอร์มืออาชีพมาเป็นอันดับหนึ่ง สำหรับบทความนี้จะเริ่มต้นด้วยการสอนให้เข้าใจในหลักการพื้นฐานของการการพัฒนาโปรแกรมในภาษา C ความรู้และความเข้าใจที่จำเป็นต่อการเป็นโปรแกรมเมอร์มืออาชีพในอนาคต เราลองเริ่มมาเรียนรู้กันอย่างคร่าวๆ กันเลยล่ะกัน โดยผู้เขียนจะอธิบายเป็นตอนๆ ทั้งหมด 8 ตอนด้วยกันได้แก่ 1. พื้นฐานโปรแกรมภาษา C (Introduction to C Programming) 2. การเขียนโปรแกรมทางเลือก (Selection Structures) 3. การเขียนโปรแกรมแบบ วนซ้ำ (Repetition & Loop) 4. ฟังก์ชัน และการเขียนโปรแกรมแยกเป็นโมดูล (Functions & Modular Programming) 5. ตารางอาเรย์ (Arrays) 6. ตัวแปรพอยเตอร์ (Pointers) 7. ตัวแปรสตริง (String) 8. โครงสร้างสตักเจอร์ (Structure) 1. พื้นฐานโปรแกรมภาษา C (Introduction to C Programming) ก่อนอื่นของแนะนำพื้นฐานเกี่ยวกับคอมพิวเตอร์กันซักนิด ก่อนที่จะเริ่มเรียนรู้ภาษา C กัน หน่วยสำคัญที่สุดของคอมพิวเตอร์ก็คือ หน่วยประมวลผลหรือที่เรียกกันว่า CPU โดยปกติ CPU จะมีภาษาของตัวเองที่เรียกว่า ภาษาเครื่อง (Machine Language) ซึ่งจะเป็นภาษาที่ประกอบไปด้วยเลขฐานสองมากมาย ดังนั้นการที่จะเขียนโปรแกรมควบคุมการทำงานของคอมพิวเตอร์ โดยใช้ภาษาเครื่องโดยตรงนั้นจึงทำได้ยาก จึงได้มีการพัฒนาตัวแปรภาษาเครื่องที่เรียกว่า โปรแกรมภาษาระดับสูงขึ้นมา หรือที่เรียกว่า High Level Languages โดยภาษาในระดับสูงเหล่านี้ จะมีลักษณะรูปแบบการเขียน (Syntax) ที่ทำให้เข้าใจได้ง่ายต่อการสื่อสารกับผู้พัฒนา และถูกออกแบบมาให้ง่ายต่อการใช้งาน และจะเปลี่ยนคำสั่งจากผู้ใช้งาน ไปเป็นเป็นภาษาเครื่อง เพื่อที่จะควบคุมการทำงานของคอมพิวเตอร์ต่อไป ตัวอย่างของโปรแกรมภาษาระดับสูง ได้แก่ COBOL ใช้กันมากสำหรับโปรแกรมทางด้านธุรกิจ, Fortran ใช้กันมากสำหรับการพัฒนาโปรแกรมด้านวิทยาศาสตร์และวิศวกรรมศาสตร์ เพราะง่ายต่อการคำนวณ, Pascal มีใช้กันทั่วไป แต่เน้นสำหรับการพัฒนาเครื่องมือสำหรับการเรียนการสอน, C & C++ ใช้ทั่วไป ปัจจุบันมีผู้เลือกที่จะใช้กันอย่างแพร่หลาย, PROLOG เน้นหนักไปทางด้านงานประเภท AI และ JAVA ใช้ได้ทั่วไป ปัจจุบันเริ่มมีผู้หันมาสนใจกันมากและเพิ่มขึ้นอย่างรวดเร็ว คราวนี้เราลองมาเตรียมตัวกันซักนิก ก่อนที่จะลงมือพัฒนาโปรแกรมคอมพิวเตอร์ ขั้นแรก เราต้องศึกษารูปแบบความต้องการของโปรแกรมที่จะพัฒนา จากนั้นก็วิเคราะห์ถึงปัญหาตลอดจนวิธีการแก้ปัญหา จากนั้นจึงนำเอาความคิดในการแก้ปัญหาอย่างเป็นขั้นตอน ไปเขียนในรูปแบบของโปรแกรมภาษาในระดับสูง ซึ่งจะอยู่ในรูปแบบของ Source Program หรือ Source Code จากนั้นเราก็จะใช้ Complier ของภาษาที่เราเลือก มาทำการ Compile Source code หรือกล่าวง่ายๆ คือแปลง Source code ของเราให้เป็นภาษาเครื่องนั่นเอง ซึ่งในขั้นตอนนี้ ผลที่ได้ เราจะเรียกว่า Object code จากนั้น Complier ก็จะทำการ Link หรือเชื่อม Object code เข้ากับฟังก์ชันการทำงานใน Libraries ต่างๆ ที่จำเป็นต่อการใช้งาน แล้วนำไปไว้ในหน่วยความจำ แล้วเราก็จะสามารถ Run เพื่อดูผลของการทำงานโปรแกรมได้ หากโปรแกรมมีข้อผิดพลาด เราก็จะทำการแก้ หรือที่เรียกกันในภาษาคอมพิวเตอร์ว่า การ Debug นั่นเอง ภาษา C เป็นโปรแกรมภาษาระดับสูง ถูกพัฒนาขึ้นในปี 1972 ที่ AT&T Bell Lab เราสามารถใช้ภาษา C มาเขียนเป็นคำสั่งต่างๆ ที่คอมพิวเตอร์สามารถเข้าใจได้ และกลุ่มของคำสั่งเหล่านี้ เราก็เรียกกันว่า อัลกอริธึม ได้มีผู้ให้คำจำกัดความของคำว่า อัลกอริธึม ว่าเป็น “A precise description of a step-by-step process that is guaranteed to terminate after a finite number of steps with a correct answer for every particular instance of an algorithmic problem that may occur.” สำหรับ Compiler ภาษา C ที่มีในปัจจุบัน มี 2 ค่ายใหญ่ๆ ที่มีผู้คนสนใจใช้กันมากได้แก่ Microsoft และ Borland การใช้งาน Compiler ทั้งสองตัวนี้ สามารถเรียนรู้ได้ไม่ยากนัก เราจึงจะมาเริ่มต้นที่การเขียนโปรแกรมในภาษา C กันเลย เราลองมาเริ่มจากตัวอย่างการเขียน ภาษา C แบบ ง่ายๆ กันก่อนกับโปรแกรม Hello World #include main() { printf("Hello World  !! "); } บรรทัดแรก #include เป็นการบอกว่าให้ทำการรวม Header file ที่ชื่อว่า stdio.h (.h = header) ซึ่งเป็น header ที่เกี่ยวข้องกับการรับและให้ข้อมูล (Standard Input Output) นอกจาก stdio.h แล้ว ก็ยังมี Header อื่นๆ ที่ผู้พัฒนาสามารถที่จะเรียกใช้งาน Function ที่จำเป็นจาก Header นั้นๆ ได้ อาทิเช่น
5519
รู้จัก Header File กันไปล่ะ คราวนี้ เราลองมาดูบรรทัดถัดไปกัน ก็คือ ฟังก์ชัน main() จะเป็นจุดเริ่มต้นของโปรแกรม และโปรแกรมทุกโปรแกรมในภาษา C จะต้องมี Function main() นี้ โดยส่วนมาก เราจะใช้ Function main() ในการกำหนดค่าเริ่มต้นต่างๆ ของโปรแกรม จากนั้นจึงเข้าสู่ Function ต่างๆ ที่ผู้พัฒนา ได้กำหนดขึ้นไว้ บรรทัดถัดมาจะเป็นเครื่องหมาย { ซึ่งเป็นเครื่องหมายบ่งบอกขอบเขตของ Function โดยขอบเขตของฟังก์ชัน จะเปิดและปิดโดยใช้เครื่องหมายเปิด { และเครื่องหมายปิด } ตามลำดับ ภายใน Function main() จะมีคำสั่ง (Statement) printf("Hello World  !! "); ซึ่ง printf เป็น Function ในภาษา C ทำหน้าที่ให้โปรแกรม ทำการแสดงผลออกทางหน้าจอว่า Hello World  !! และทุกครั้ง ผู้พัฒนาจะต้องทำการจบคำสั่งหรือ Statement ด้วยเครื่องหมาย semi-colon ; ดังนั้นรูปแบบของการเขียนโปรแกรม จึงเขียนออกมาในรูปแบบดังนี้ // ข้อความที่อยู่ข้างหลังเครื่องหมาย // จะเป็นคำอธิบายโปรแกรม #include void main() { constant declarations; // การกำหนดค่าคงที่ต่างๆ variable declarations; // การกำหนดตัวแปรต่างๆ executable statements; // คำสั่งการทำงานของโปรแกรม } การอ่านข้อมูลและการแสดงผล (Input & Output) รูปแบบการใช้งานฟังก์ชัน printf จะทำการพิมพ์ในรูปแบบที่ เริ่มต้นด้วย Format ที่ต้องการจะพิมพ์ และตามด้วยตัวแปรที่ต้องการพิมพ์ ดังนี้ printf( const char *format [, argument]... ); สำหรับการนำข้อมูลเข้าก็เช่นกัน จะใช้ฟังก์ชัน scanf ซึ่งจะเป็นฟังก์ชันสำหรับอ่านข้อมูลจากคีย์บอร์ด และจะนำข้อมูลที่ User ทำการพิมพ์ไปเก็บไว้ใน argument โดยแต่ละ argument จะต้องเป็นตัวแปรที่เรียกว่า pointer (รายละเอียดจะได้กล่าวต่อไป) และมีชนิดที่ตัวแปรที่สัมพันธ์กับที่ได้กำหนดไว้ใน Format รูปแบบการใช้งานของฟังก์ชัน scanf สามารถเขียนได้ดังนี้ scanf( const char *format [,argument]... );

หน้าที่ 2 - ตัวแปร (Variables)
ตัวแปร (Variables) ตัวแปรจะเป็นชื่อที่ใช้ในการบอกจำนวนหรือปริมาณ ซึ่งสามารถที่จะทำการเปลี่ยนแปลงจำนวนได้ด้วยโปรแกรมคอมพิวเตอร์ การตั้งชื่อตัวแปร จะต้องตั้งชื่อให้แตกต่างไปจากชื่อของตัวแปรอื่นๆ ยกตัวอย่างชื่อของตัวแปร ได้แก่ x, y, peter, num_of_points และ streetnum เป็นต้น โดยปกติการเขียนโปรแกรมที่ดี ควรจะตั้งชื่อตัวแปรให้สอดคล้องกับการทำงานหรือหน้าที่ของตัวแปรนั้นๆ เพราะเมื่อถึงเวลาต้องมาทำการปรับปรุงแก้ไขโปรแกรม จะสามารถทำได้โดยไม่ยากนัก ในภาษา C หรือ C++ ได้มีกฏในการตั้งชื่อตัวแปรที่สามารถใช้งานได้ดังนี้ - ชื่อตัวแปรจะต้องขึ้นต้นด้วยตัวอักษร - ชื่อตัวแปรจะประกอบไปด้วย ตัวอักษร ตัวแลข และ _ ได้เท่านั้น - ชื่อตัวแปรจะต้องไม่ใช่ชื่อ reserved word (ชื่อที่มีการจองไว้แล้ว) ตัวอย่างของชื่อตัวแปรที่สามารถนำมาใช้ตั้งชื่อได้ ได้แก่ length, days_in_year, DataSet1, Profit95, Pressure, first_one และตัวอย่างของชื่อ ที่ไม่สามารถนำมาใช้เป็นชื่อตัวแปรได้ ยกตัวอย่างเช่น day-in-year, 1data, int, first.val เป็นต้น reserved word (ชื่อที่มีการจองไว้แล้ว) Reserved words หรือตัวแปรที่ได้จองไว้แล้วนั้น จะประกอบไปด้วยตัวอักษรตัวเล็กทั้งหมด และจะมีความสำคัญสำหรับภาษา C++ และจะไม่นำมาใช้ด้วยวัตถุประสงค์อื่นๆ ตัวอย่างของ Reserved words ได้แก่ and, bool, break, case, catch, char, class, continue, default, delete, do, double, if , else, enum, export, extern เป็นต้น นอกจากนี้ในภาษา C หรือ C++ ชื่อตัวแปร ที่ประกอบไปด้วยอักษรเล็ก หรือใหญ่ ก็มีความแตกต่างกัน หรือที่เรียกว่า Case sensitive ยกตัวอย่างเช่น ‘X’ และ ‘x’ เป็นตัวแปรต่างกัน ‘peter’ และ ‘Peter’ เป็นตัวแปรต่างกัน ‘bookno1’ และ ‘bookNo1’ เป็นตัวแปรต่างกัน ‘XTREME’ และ ‘xtreme’ เป็นตัวแปรต่างกัน ‘X1’ และ ‘x1’ เป็นตัวแปรต่างกัน ‘int’ และ ‘Int’ เป็นตัวแปรต่างกัน การกำหนดชนิดของตัวแปร (Declaration of Variables) ในภาษา C หรือ C++ (และโปรแกรมในภาษาอื่นๆ) ตัวแปรทุกตัวที่จะมีการเรียกใช้ในโปรแกรมจำเป็นต้องมีการกำหนดชนิดของตัวแปรนั้นๆ ก่อนที่จะทำการเรียกใช้ตัวแปร การกำหนดชนิดของตัวแปรมีวัตถุประสงค์หลัก 2 ประการได้แก่ - เป็นการบอกชนิด และตั้งชื่อตัวแปรที่จะเรียกใช้ ชนิดของตัวแปรจะทำให้คอมไพเลอร์สามารถแปลคำสั่งได้อย่างถูกต้อง (ยกตัวอย่างเช่น ใน CPU คำสั่งที่ใช้ในการบวกตัวเลขจำนวนเต็ม 2 จำนวน ย่อมแตกต่างจากคำสั่งที่จะบวกจำนวนจริง 2 จำนวนเข้าด้วยกัน) - ชนิดของตัวแปร ยังเป็นบ่งบอกคอมไพเลอร์ให้ทราบว่าจะต้องจัดเตรียมเนื้อที่ให้กับตัวแปรตัวนั้นมากน้อยเท่าใด และจะจัดวางตัวแปรนั้นไว้แอดเดรส (Address) ไหนที่สามารถเรียกมาใช้ใน code ได้ สำหรับในบทความนี้จะพิจารณาชนิดตัวแปร 4 ชนิดที่ใช้กันมากได้แก่ int, float, bool และ char int ชนิดตัวแปรที่สามารถแทนค่าจำนวนเต็มได้ทั้งบวกและลบ โดยปกติสำหรับคอมพิวเตอร์ทั่วไป คอมไพเลอร์ จะจองเนื้อที่ 2 ไบต์ สำหรับตัวแปรชนิด int จึงทำให้ค่าของตัวแปรมีค่าตั้งแต่ -32768 ถึง +32768 ตัวอย่างของค่า int ได้แก่ 123 -56 0 5645 เป็นต้น floatชนิดของตัวแปรที่เป็นตัวแทนของจำนวนจริง หรือตัวเลขที่มีค่าทศนิยม ความละเอียดของตัวเลขหลังจุดทศนิยมขึ้นอยู่กับระบบคอมพิวเตอร์ โดยปกติแล้ว ตัวแปรชนิด float จะใช้เนื้อที่ 4 ไบต์ นั่นคือจะให้ความละเอียดของตัวเลขหลังจุดทศนิยม 6 ตำแหน่ง และมีค่าอยู่ระหว่าง -1038 ถึง +1038 ตัวอย่างของค่า float ได้แก่ 16.315 -0.67 31.567 bool ชนิดของตัวแปรที่สามารถเก็บค่าลอจิก จริง (True) หรือ เท็จ (False) ตัวแปรชนิดนี้ เป็นที่รู้จักกันอีกชื่อคือ ตัวแปรบูลีน (Boolean) ตัวอย่างของตัวแปรชนิด bool ได้แก่ 1 0 true false (เมื่อ 1 = true และ 0 = false) char เป็นชนิดตัวแปรที่เป็นตัวแทนของ ตัวอักษรเพียงตัวเดียว อาจเป็นตัวอักษร ตัวเลข หรือตัวอักขระพิเศษ โดยปกติตัวแปรชนิดนี้จะใช้เนื้อที่เพียง 1 ไบต์ ซึ่งจะให้ตัวอักษรในรูปแบบที่แตกต่างกันได้ถึง 256 ค่า การเขียนรูปแบบของ char หลายๆ ตัว โดยปกติ จะอ้างอิงกับ American Standard Code for Information Interchange (ASCII) ตัวอย่างของตัวแปรชนิด char ได้แก่ '+' 'A' 'a' '*' '7' การกำหนดชนิดของตัวแปร สามารถเขียนได้อยู่ในรูป type identifier-list; เมื่อ type บ่งบอกชนิดของตัวแปร ส่วน identifier-list เป็นการกำหนดชื่อของตัวแปร ซึ่งอาจจะมีมากกว่า 1 ตัวแปร และจะแยกตัวแปรแต่ละตัวออกจากกันด้วยเครื่องหมาย comma (,) ตัวอย่าง รูปแบบของการกำหนดชนิดของตัวแปร ได้แก่
int i, j, count;
 float sum, product;
 char ch;
 bool passed_exam;
มาถึงตอนนี้ เราก็จะสามารถปรับปรุงการเขียนโปรแกรมแบบง่ายๆ ได้ดังนี้
#include 
main()
{
   int its_price;
   printf("How much is that ? ");
   scanf("%d", &its_price);
   printf("oh! %d ?, hmmm...., too expensivenn",its_price);
}
จาก code ข้างบน ผู้อ่านจะเห็น %d เมื่อมีการเรียกใช้ฟังก์ชัน scanf และ printf ทั้งนี้ %d จะเป็น format ที่ใช้บ่งบอกชนิดของตำแหน่ง (Place Holders) ที่จะมีการส่งข้อมูล โดยในที่นี้ %d หมายถึงตำแหน่งของจำนวนเต็ม หรือ int นั่นเอง ตัวอย่างของ Place Holders อื่นๆ สามารถแสดงได้ดังตาราง คราวนี้ลองมาดูตัวอย่างของการใช้ Place Holders
printf("C=%f, F=%f",cel,fah);
printf("He wants to score %d goals today",9);
เมื่อ % เป็นการบ่งบอกตำแหน่งเริ่มต้นของ Place Holder จากนั้น ตัวอักษร f ตัวแรก จะบ่งบอกถึง ตัวแปรcel ว่ามีค่าเป็นจำนวนจริง (Float) ส่วน f ตัวทีสอง จะบ่งบอกคอมไพเลอร์ว่า ตัวแปร fah ก็มีค่าเป็นจำนวนจริงเช่นกัน นอกจากนี้ Place holder %d และ %f ยังสามารถใช้กับการกำหนดตำแหน่งตัวเลขตามต้องการได้ ยกตัวอย่างเช่น สมมุติให้ x=235; และ y=6.54321;
5520
การให้กำหนดค่าตัวแปร (Variable Assignment) เราสามารถกำหนดค่าให้กับตัวแปรได้ ด้วยเครื่องหมาย = ยกตัวอย่างเช่น int name; // กำหนดตัวแปร name ที่เก็บค่าจำนวนเต็ม name = 23; // กำหนดให้ตัวแปร name มีค่าเป็น 23 ในขณะเดียวกัน เราสามารถใช้เครื่องหมาย = ระหว่างตัวแปรกับตัวแปร หรือตัวแปรกับจำนวนใดๆ ได้ อาทิเช่น
change = x1 - x2;
mean = (x1 + x2)/2;
x = x + 1;
ตอนนี้เราลองมาเขียนโปรแกรมอย่างง่าย เพื่อทำการแก้ปัญหาทางคณิตศาสตร์ ด้วยการแปลงค่า อุณหภูมิ ในหน่วยของ ฟาเรนไฮต์ เป็น เซลเซียส เมื่ออุณหภูมิในหน่วยฟาเรนไฮต์ มีค่า = 85 และเป็นที่ทราบกันดีว่า ความสัมพันธ์ระหว่าง องศาฟาเรนไฮต์ และ เซลเซียส สามารถเขียนได้อยู่ในรูปของสมการ
5521
การเขียนโปรแกรม เพื่อแก้ปัญหา การแปลงค่า 85 ฟาเรนไฮต์ให้เป็นเซลเซียส สามารถเขียนได้ดังนี้
#include 
void main()
{
     float F;
 float C;

 F = 85;
 C = 5*(F-32)/9;
 printf("the result is %f",C);
}
อีกตัวอย่าง ของโปรแกรม การบวกค่าจำนวนเต็ม 2 จำนวนเข้าด้วยกัน แล้วแสดงผลลัพธ์ออกทางหน้าจอ การเขียนโปรแกรมเพื่อแก้ปัญหานี้ สามารถเขียนได้ดังนี้
#include 
void main()
{
    int N1, N2, Sum;
 
 printf("please input an integer number : ");
 scanf("%d",&N1);
 printf("please input another integer number : ");
 scanf("%d",&N2);

 Sum = N1 + N2;
 printf("so, %d + %d = %d",N1,N2,Sum);
}
จากตัวอย่างการเขียนโปรแกรมข้างต้น จะเห็นว่ามีการคำนวณทางคณิตศาสตร์เข้ามาเกี่ยวข้อง คราวนี้เราลองมาดู การคำนวณในภาษา C กันว่าจะเขียนกันได้อย่างไรบ้าง
5522


หน้าที่ 3 - การเปรียบเทียบ แบบมีทางเลือก (Selection Structures)
2.การเขียนโปรแกรมแบบมีทางเลือก (Selection Structures) การเขียนโปรแกรมแบบมีทางเลือก จะสามารถทำให้โปรแกรมสามารถตัดสินใจหรือเปรียบเทียบ จากนั้นก็จะเลือกดำเนินการไปในทิศทางหนึ่งจากสองทิศทาง ขึ้นอยู่กับผลที่ได้จากการเปรียบเทียบนั้น เงื่อนไข (Condition) - เป็นตัวกำหนดเงื่อนไขที่ผู้พัฒนาโปรแกรมได้สร้างขึ้นมา - ผลลัพธ์ที่ได้จากเงื่อนไข จะมีค่า จริงหรือ เท็จ โครงสร้างของเงื่อนไข (Condition Control Structures) ประโยคเงื่อนไขสามารถที่จะเขียนให้อยู่ในรูปภาษา C จะเขียนได้ดังนี้ if condition then A else B ซึ่งหมายความว่า ถ้าเงื่อนไข (condition) มีค่าเป็นจริง ก็จะดำเนินการทำคำสั่ง A มิเช่นนั้นก็จะทำคำสั่ง B ตัวอย่างของการเขียนโครงสร้างทางเลือกในภาษา C สามารถเขียนได้ดังนี้
if (x < y)
 a = x * 2;
else
 a = x + y;
ความหมายของ code ดังกล่าว หมายความว่า ถ้า ค่า x มีค่าน้อยกว่า y แล้ว a = x*2 แต่ถ้า x มีค่ามากกว่าหรือเท่ากับ y แล้ว a = x+y นั่นเอง รูปแบบของเงื่อนไข ส่วนใหญ่จะอยู่ในรูป “ตัวแปร โอเปอเรเตอร์ ตัวแปร” โอเปอเรเตอร์ที่กล่าวถึงนี้จะมีอยู่ 2 แบบ ด้วยกันคือ โอเปอเรเตอร์สัมพันธ์ (Relational Operator) และ โอเปอเรเตอร์ลอจิก (Logical Operator) โอเปอเรเตอร์สัมพันธ์ที่ใช้ในภาษา C มีดังต่อไปนี้
5523
if ( condition1 ) 
   statement1 ; 
else 
      if ( condition2 ) 
           statement2 ; 
           . . . 
        else if ( condition-n ) 
                  statement-n ; 
                else 
                  statement-e ;
ยกตัวอย่างของโปรแกรม Nested if สามารถเขียนได้ดังนี้
if (x < 0.25)
  count1++;
else if (x < 0.5)
           count2++;
        else if (x < 0.75)
                  count3++;
                else
                    count4++;
นอกจากรูปแบบของ if-else แล้ว เรายังสามารถใช้เครื่องหมาย ? มาประยุกต์ในการเขียน code เพื่อให้ได้ความหมายเดียวกันกับ if-else ดังแสดงให้เห็นดังนี้
if (x < y)
 a = x * 2;
else
 a = x + y;
สามารถเขียนได้ในอีกรูปแบบหนึ่งคือ a = x < y ? x*2: x+y ; // ซึ่งจะให้ความหมายเดียวกันกับ code ข้างบนนั่นเอง ในบางครั้งที่เราต้องเขียนโปรแกรมแบบมีทางเลือก โดยบางครั้งเราต้องการให้มีทางเลือกมากว่า 2 ทาง Nested if เป็นวิธีหนึ่งที่สามารถใช้แก้ปัญหาได้ แต่เพื่อให้ง่ายขึ้น ในภาษา C เราจึงสามารถใช้คำสั่ง switch ได้ โดยรูปแบบการเขียน คำสั่ง switch สามารถเขียนให้อยู่ในรูป
switch (selector) 
      {
      case label1: statement1;
          break;
      case label2: statement2;
          break;
          ...
      case labeln: statementn;
          break;
      default: statementd; // optional
          break;
      }
โดยที่ selector จะต้องเป็นจำนวนเต็ม ตัวอักษร หรือผลลัพธ์ของการกระทำที่ให้เลขจำนวนเต็มหรือตัวอักษร ตัวอย่างของการเขียน code โดยมีการเรียกใช้คำสั่ง switch สามารถเขียนได้ดังนี้ switch (i) { case 1 : grade = 'A'; break; case 2 : grade = 'B'; break; case 3 : grade = 'c'; break; default : printf("%c not in range", i); break; } โดยหลักการของ switch คือ compiler จะทำการเปรียบเทียบค่าของ selector เทียบกับ label ถ้าไม่ตรงกับ label ใดๆ ก็จะเข้าไปทำในคำสั่งของ default นอกจากนี้ การใส่คำสั่ง break หรือไม่มีคำสั่ง break ก็จะให้ผลลัพธ์ที่แตกต่างกัน ดังแสดงให้เห็นดังตัวอย่างต่อไปนี้ (ทดลอง Run แล้วจะเห็นความแตกต่าง)
5524
5525
การเปรียบเทียบตัวอักษร คุณผู้อ่านทราบกันหรือไม่ว่า ตัวอักษรสามารถเปรียบเทียบค่ากันได้ เบื้องต้นเราต้องทราบก่อนว่า ตัวอักษรมีค่าอย่างไรกันบ้าง  ตัวอักษรตัวเล็ก ‘a’ มีค่า 97 ไปจนถึง ‘z’ มีค่า 122  ตัวอักษรตัวใหญ่ ‘A’ มีค่า 65 ไปจนถึง ‘Z’ มีค่า 90 ตัวอย่างของการเปรียบเทียบตัวอักษร สามารถแสดงให้เห็นได้ดังนี้  ‘9’ >= ‘0’ มีค่าเป็นจริง (1)  ‘a’ < ‘e’ มีค่าเป็นจริง (1)  ‘B’ <= ‘A’ มีค่าเป็นเท็จ (0)  ‘a’ <= ‘A’ ขึ้นอยู่กับระบบ แต่ส่วนใหญ่ เป็นเท็จ  ‘a’ <= ‘c’ && ‘c’ <= ‘z’ มีค่าเป็นจริง คราวนี้เราลองมาดูโจทย์กัน สมมุติว่า เราจะเขียนโปรแกรม เพื่ออ่านค่าตัวอักษร 4 ตัว แล้ว เราต้องการที่จะเปลี่ยนตัวอักษรแต่ละตัว ให้เป็นตัวอักษรใหญ่ หรือเล็กที่ตรงข้ามกับค่าที่รับเข้าไป ยกตัวอย่างเช่น PooH ให้เปลี่ยนเป็น pOOh เราจะเขียนโปรแกรมอย่างไร คำตอบ วิธีหนึ่งที่สามารถทำได้ คือใช้ Nested-if ดังนี้ #include void main() { char A, B, C, D; printf("Input 4 charactersn"); scanf("%c %c %c %c", &A, &B, &C, &D); if((A <= 90)&&(A >= 65)) A = (A - 65) + 97; else if ((A >= 97)&&(A <= 122)) A = (A-97) + 65; else A = A; if((B <= 90)&&(B >= 65)) B = (B - 65) + 97; else if ((B >= 97)&&(B <= 122)) B = (B-97) + 65; else B = B; if((C <= 90)&&(C >= 65)) C = (C - 65) + 97; else if ((C >= 97)&&(C <= 122)) C = (C-97) + 65; else C = C; if((D <= 90)&&(D >= 65)) D = (D - 65) + 97; else if ((D >= 97)&&(D <= 122)) D = (D-97) + 65; else D = D; printf("The answer is %c %c %c %cn", A, B, C, D);

หน้าที่ 4 - การเขียนโปรแกรมแบบ วนซ้ำ (Loop)
3.การเขียนโปรแกรมแบบ วนซ้ำ (Repetition & Loop) กระบวนการหนึ่งที่สำคัญในการออกแบบอัลกอริทึม ก็คือความสามารถในการวนลูปของการทำงานของกลุ่มคำสั่งตามที่นักพัฒนาต้องการ ดังนั้นสำหรับตอนนี้ ก็จะนำเสนอการพัฒนาโปรแกรมเพื่อให้บางส่วนของคำสั่งสามารถมีการวนซ้ำได้หลายครั้ง สำหรับคำสั่งที่สามารถใช้ในการเขียนโปรแกรมแบบวนซ้ำในภาษา C ได้แก่ While, Do-while และ For ตัวอย่างของการใช้คำสั่ง while, for และ do-while สามารถเขียนให้เห็นได้ดังตาราง ซึ่งผลลัพทธ์ของโปรแกรมทั้ง 3 ข้างต้นจะให้ผลลัพท์ที่เหมือนกัน คือจะแสดงผลบนหน้าจอเป็น i = 0 i = 1 i = 2 i = 3 i = 4 i = 5 i = 6 คราวนี้เราลองมาดูโครงสร้างของการใช้งานแต่ละคำสั่งกัน while ( condition ) // เมื่อ เงื่อนไข (condition) เป็นจริง ก็จะทำการวนซ้ำ ใน statement ถัดไป statement ยกตัวอย่างเช่น
sum = 0.0;
x = 5;
while (x > 0.0)
   {
    sum += x;
    x = x – 1;
   }
ในที่นี้จะเห็นว่า ค่า x มีค่าเริ่มต้นเท่ากับ 5 ซึ่ง 5 > 0 เงื่อนไขของคำสั่ง while เป็นจริง จึงทำคำสั่งถัดมาคือ sum += x; หมายความว่า sum = sum + x = 5 จากนั้นค่า x ก็มีค่าลดลงไป 1 เหลือ 4 ก็จะทำการ check เงื่อนไขว่า 4 > 0 หรือไม่ เมื่อเงื่อนไขเป็นจริง ก็จะทำการวนซ้ำ sum ก็จะมีค่าเป็น 5 + 4 = 9 และ x ก็จะมีค่าลดลงเหลือ 3 และดำเนินการวนซ้ำเช่นนี้จนกระทั่ง x มีค่าเป็น 0 ซึ่งค่า 0 ไม่ได้มีค่ามากกว่า 0.0 เงื่อนไขจึงเป็นเท็จ โปรแกรมจึงจะจบการวนซ้ำ คราวนี้เราลองมาดูตัวอย่างของการใช้คำสั่ง while ในการเขียนโปรแกรมแบบวนซ้ำ และผลลัพท์ที่ได้
x=0;
while( x <=2 ){
   printf("%d %dn",x, x*2);
}

ผลลัพท์ที่ได้จะได้ดังนี้
 0 0
 0 0
 0 0
 :   :
 0 0  (infinite loop)
การที่ผลลัพท์ออกมาเช่นนี้ ก็เนื่องจากว่า x มีค่าเริ่มต้น 0 และเงื่อนไข x <= 2 เป็นจริงตลอด โปรแกรมจึงทำการพิมพ์ค่า 0 0 ออกมา และเนื่องจากค่า x ไม่มีการเปลี่ยนแปลง เงื่อนไขจึงเป็นจริงตลอด โปรแกรมจึงแสดงผลบนหน้าจอโดยไม่หยุดนั่นเอง อีกตัวอย่างของการใช้งาน while ในการเขียนโปรแกรมแบบวนซ้ำ แสดงได้ดังนี้
scanf(“%d”,&n);
a = 10;
while (a > n) {
   printf(“%dn”,a);
   a = a-1;
}
ผลลัพท์ของโปรแกรมจะสามารถแสดงให้เห็นได้ดังนี้
10
 9
 8
 7
คราวนี้เราลองมาแก้โจทย์ปัญหา การหาค่า ห.ร.ม (หารร่วมมาก) ของตัวเลข 2 ตัวใดๆ โดยอัลกอริทึม Euclidean โดยอัลกอริทึมดังกล่าว จะทำการแปลงค่าตัวเลข 2 ตัวเลขบวกใดๆ (m, n) เป็นค่า (d, 0) โดยการนำตัวเลขที่มีค่ามาก นำมาหารด้วยตัวเลขที่มีค่าน้อยกว่า นำค่าเศษที่หารได้มาแทนตัวเลขที่มีค่ามากกว่า ทำเช่นนี้จนกระทั่งได้ค่าเศษจากการหารมีค่าเป็น 0 ตัวเลขอีกตัวก็จะเป็นค่า ห.ร.ม. ยกตัวอย่างเมื่อเราทำการ Run โปรแกรม จะได้ผลดังนี้ Enter two positive integers: 532 112 The g.c.d. of 532 and 112 is 28 คราวนี้เราลองมาดูการเขียนโปรแกรมเพื่อแก้ปัญหาดังกล่าวข้างต้น สามารถเขียนได้ดังนี้
#include 
void main()
{
 int A, B, start;
     printf("Enter two positive intergers: ");
 scanf("%d %d", &A, &B);
 if(A < B) start = A;
 else start = B;
 while(((A%start) != 0)||((B%start) != 0))
 {
  start = start-1; 
 }
 printf("The g.c.d of %d and %d is %dn", A, B, start);
}
การดำเนินการทางคณิตศาสตร์ สามารถเขียนให้อยู่ในรูปแบบสั้นๆ ได้ ดังตัวอย่างในตารางดังนี้
5526
ความแตกต่างระหว่าง i++ และ ++i i++ และ ++i จะมีความหมายใกล้เคียงกันมาก จะแตกต่างเพียง การจัดลำดับในการคำนวณ เมื่อต้องนำไปใช้กับตัวแปรตัวอื่น A = 10; C = A++; // A= 11, C = 10 A = 10; C = ++A; // A = 11, C = 11 A = 10; C = A--; // A = 9, C = 10 A = 10; C = --A; // A = 9, C = 9 โครงสร้างการเขียนโปรแกรมแบบวนซ้ำโดยใช้คำสั่ง For คำสัง for สามารถเขียนให้อยู่ในรูปแบบได้ดังนี้ for ( เริ่มต้น ; เงื่อนไข ; เปลี่ยนแปลง ) statement; เมื่อเริ่มต้น เป็นการกำหนดค่าตัวแปรเริ่มต้นที่ต้องการ ส่วนเงื่อนไขหากค่าลอจิกมีค่าเป็นจริง ก็จะทำตามในโครงสร้างของการวนซ้ำคือ run คำสั่ง statement แต่ถ้าเป็นเท็จก็จะออกจากโครงสร้างการวนซ้ำ ส่วนเปลี่ยนแปลง จะทำการปรับค่าของตัวแปรที่ต้องการ ยกตัวอย่างเช่น
for ( count=0 ; count < 10 ; count++)
  {
   printf(“count = %dn”,count);
  }
ใน code ข้างต้น ตัวแปร count จะเริ่มต้นจากค่า 0 ซึ่งค่า 0 มีค่าน้อยกว่า 10 ก็จะทำคำสั่ง print ค่าของตัวแปร count จากนั้นค่า count ก็จะเพิ่มค่าเป็น 1 เงื่อนไข count < 10 ก็ยังคงเป็นจริง ก็จะทำการพิมพ์ ค่าของตัวแปร count วนซ้ำเช่นนี้ จนกระทั่ง count มีค่าเพิ่มขึ้นจนเป็น 10 เงื่อนไขก็จะเป็นเท็จ และจบโครงสร้างของการวนซ้ำ การเปลี่ยนแปลงค่าของตัวแปร อาจจะมีการเปลี่ยนแปลงมากกว่า 1 ค่า ยกตัวอย่างเช่น
for ( count=0 ; count < 10 ; count += 2)  // ตัวแปร count มีค่าเปลี่ยนแปลงเพิ่มขึ้นครั้งละ 2
{
   printf(“count = %dn”,count);
}
for ( count=10 ; count > 5 ; count -= 2)   // ตัวแปร count มีค่าเปลี่ยนแปลงลดลงครั้งละ 2
{  
   printf(“count = %dn”,count);
}
นอกจากนี้เรายังสามารถใช้ตัวแปร เป็นการกำหนด ค่าเริ่มต้น เงื่อนไข และ เปลี่ยนแปลงได้ ยกตัวอย่างเช่น
start = 0; end = 20; step=3;
for ( count=start ; count < end ; count += step)
{
   printf(“count = %dn”,count);
}
คราวนี้ เราลองมาทดลองเขียนโปรแกรม โดยให้โปรแกรม สามารถรับค่าตัวเลขใดๆ และแสดงค่าในรูปแบบดังตัวอย่างต่อไปนี้
5527
Input the number > 4

0
0 1
0 1 2
0 1 2 3
0 1 2
0 1
0

เราสามารถแก้ปัญหาข้างต้น โดยใช้โครงสร้างการเขียนโปรแกรมแบบวนซ้ำดังต่อไปนี้
#include 
void main()
{
 int number, i, j;
     printf("Enter number: ");
 scanf("%d", &number);
 for(j= 0; j< number; j++)
 {
  for(i=0; i<= j; i++)
  {
   printf("%d ", i);
  }
  printf("n");
 }
 for(j= number-1; j>= 0; j--)
 {
  for(i=0; i< j; i++)
  {
   printf("%d ", i);
  }
  printf("n");
 }
}
โครงสร้างการเขียนโปรแกรมแบบวนซ้ำโดยใช้คำสั่ง do-while รูปแบบของการเขียน code สำหรับโปรแกรมแบบวนซ้ำที่ใช้ do-while สามารถเขียนให้อยู่ในรูปทั่วไปได้ดังนี้ do statement while ( เงื่อนไข ); ตัวอย่างของโครงสร้าง do-while สามารถเขียนได้ดังนี้
sum = 0.0;
scanf(“%f”, &x);
do {
    sum += x;
    scanf(“%f”, &x);
  }
while (x > 0.0);
โปรแกรมข้างต้นจะทำการอ่านค่าจะ keyboard เมื่อ User พิมพ์ค่าที่มีค่ามากกว่าศูนย์ ก็จะทำการบวกค่าเหล่านี้ไปที่ตัวแปร sum จนกระทั่ง User พิมพ์ ตัวเลข 0 หรือค่าที่น้อยกว่า ศูนย์ ทำให้เงื่อนไขเป็นเท็จ และโปรแกรมจึงจะออกจากโครงสร้าง do-while คราวนี้เราลองมาเขียนโปรแกรมที่ใช้โครงสร้าง do-while โดยโจทย์กำหนดให้ว่า ให้โปรแกรมสามารถรับค่าตัวเลขใดๆ (X) และ แสดงผลของตัวเลข ระหว่าง 0 ถึง X ที่สามารถหารด้วย 4 ลงตัว
#include 
void main()
{  
 int number, i;
 printf("enter the numbern");
 scanf("%d", &number);
            i = 0;
 do
 {
  if((i % 4) == 0) printf("%d ", i);
                       i++;
 }
            while(i <= number);
}
ตอนนี้ผู้อ่านก็คงจะรู้จัก การเขียนโปรแกรมแบบวนซ้ำกันแล้วนะ ต่อไป เราก็จะไปเรียนรู้เกี่ยวกับการเขียนโปรแกรมแบบแยกเป็นโมดูลกัน

หน้าที่ 5 - ฟังก์ชัน (Functions) และ โปรแกรมแยกเป็นโมดูล (Modular Programming)
4.ฟังก์ชัน และการเขียนโปรแกรมแยกเป็นโมดูล (Functions & Modular Programming) สำหรับนักพัฒนา ที่ได้ทำการพัฒนาโปรแกรมมามากๆ บางครั้ง จำเป็นต้องเขียนโปรแกรมที่มีขนาดใหญ่และมีความสลับซับซ้อน จึงจำเป็นต้องหาวิธีในการพัฒนาโปรแกรมที่ดี ซึ่งสามารถทำได้ด้วยการ แตกปัญหาใหญ่ออกเป็นปัญหาย่อยๆ แล้วแก้ปัญหาย่อยออกไปที่ละส่วนจนกว่าจะหมด ซึ่งจะช่วยให้แก้ปัญหาใหญ่ๆ ได้สำเร็จนั่นเอง ซึ่งเราเรียกกันว่า วิธีแบ่งแยกแล้วพิชิต (Divide and Conquer) ซึ่งจะเป็นแนวการแก้ปัญหาแบบจากบนลงล่าง (Top down approach) ดังแสดงให้เห็นดังภาพที่ 4.1
5529
การแตกปัญหาออกเป็นฟังก์ชันย่อยๆ มีข้อดีดังนี้ 1) การแยกปัญหาที่จะใช้ในการเขียนโปรแกรมออกเป็นฟังก์ชันย่อยๆ จะช่วยให้เขียนโปรแกรมได้ง่ายขึ้นเพราะปัญหามีความซับซ้อนน้อยลง 2) การแยกปัญหาที่จะใช้ในการเขียนโปรแกรมออกเป็นฟังก์ชันย่อยๆ สามารถแก้ปัญหาตามที่โปรแกรมต้องทำ โดยมีโอกาสที่จะผิดพลาดน้อยลงเนื่องจากได้ทดสอบแก้ไขข้อผิดพลาดภายในฟังก์ชันย่อยๆ ก่อนรวมกันเป็นโปรแกรมใหญ่แล้ว 3) การแยกปัญหาออกเป็นฟังก์ชันย่อยนั้นมีประโยชน์ ที่ทำให้เราสามารถใช้ฟังกชันย่อยๆ เหล่านี้กลับไปใช้กับโปรแกรมอื่นๆ ได้ด้วย 4) การนำฟังกชันย่อยๆ เหล่านี้กลับมาใช้อีก จะช่วยลดขนาดของโปรแกรมลง และยังช่วยลดเวลาและค่าใช้จ่ายในการพัฒนาและการซ่อมบำรุงโปรแกรมได้อีกด้วย เพราะไม่ต้องเสียเวลาในการเขียนฟังก์ชันซ้ำ นอกจากฟังก์ชันย่อยที่ยังไม่ได้เขียนมาก่อน ตัวอย่างการเขียนโปรแกรมออกเป็นโมดูลต่างๆ จะแสดงให้เป็นดังผังในภาพที่ 4.2 ซึ่งในภาพดังกล่าวได้แยกโปรแกรม Main ออกเป็นส่วนๆ คือ
5530
1) ส่วนรับข้อมูล (Input) ซึ่งจะเป็นไปตามความต้องการของผู้ใช้ เช่นการป้อนข้อมุล หรือ การอ่านไฟล์ข้อมูล 2) ส่วนการคำนวณ (CAL) ซึ่งประกอบด้วยฟังก์ชันที่ใช้กับการคำนวณ ได้แก่ i. AVG สำหรับคำนวณค่าเกรดเฉลี่ยสำหรับเทอมปัจจุบัน ii. GPA สำหรับคำนวณเกรดเฉลี่ยสะสม 3) ส่วนการแสดงผล (Display) ซึ่งเป็นการแสดงผลบนจอภาพ หรือจะพิมพ์ผลออกมาก็ได้ตามความต้องการของผู้ใช้โปรแกรม ที่กำหนดให้ผู้เขียนโปรแกรมทำให้สำเร็จตามเป้าหมาย ภาพที่ 4.2: ตัวอย่างการเขียนโปรแกรมคำนวณค่าเกรดเฉลี่ย และ เกรดเฉลี่ยสะสมออกเป็นโมดูล ส่วนในการตั้งชื่อฟังก์ชันนั้น ก็มีข้อกำหนดดังนี้ 1) ห้ามขึ้นต้นด้วยตัวเลข 2) ห้ามเอาชื่อตารางอาเรย์ ชื่อตัวแปร หรือ คำสำคัญ (keywords) มาตั้งชื่อฟังก์ชันโดยเด็ดขาด 3) ในการใช้งานจริง นั้น ไม่ควรตั้งชื่อฟังก์ชันโดยไม่สื่อความหมายถึงการทำงานของฟังก์ชัน เพราะจะทำให้ลำบากในการซ่อมบำรุงโปรแกรม โดยทั่วไปแล้วในการประกาศฟังก์ชันนั้น จะต้องมีการกำหนด type ให้ตัวแปรร่วมภายในฟังก์ชันด้วยเสมอ ดังตัวอย่างต่อไปนี้ ชนิดของฟังก์ชัน[function-type] ชื่อฟังก์ชัน [function-name] (บัญชีตัวแปรร่วม [parameter-list])
{
  การประกาศตัวแปรเฉพาะที่; [local-definitions declaration;]
  กลไกการทำงานของฟังก์ชัน; [function-implementation;]
  การคืนค่าถ้าชนิดฟังก์ชันไม่เป็น void; [return statement if function type NOT void]
}

ยกตัวอย่างเช่น

float distance(float x, float y) // float คือ ชนิดของฟังก์ชัน ส่วน distance คือ ชื่อฟังก์ชัน
{    // float x, float y คือ บัญชีตัวแปรร่วม
 float dist;  // float dist คือ การประกาศตัวแปรเฉพาะที่;
 dist = sqrt(x*x+y*y); // dist = ระยะห่างระหว่างพิกัด (x,y) ไป (0,0) 
 return dist ;
}
ก่อนจะทำการเรียกใช้ฟังก์ชัน จำเป็นต้องมี การกำหนดฟังก์ชัน (function prototype) ซึ่งเป็น copy ของ function heading และมีข้อกำหนดดังนี้ 1) ตัวแปรร่วมในฟังก์ชัน ที่ประกาศไว้ และ ตัวแปรร่วมขณะเรียกใช้ฟังกชันนั้นต้องมีจำนวนเท่ากันและต้องมี type ตรงกัน มิฉะนั้นจะเกิด error ขึ้น 2) ต้องกำหนดการทำงานของฟังก์ชันก่อนการเรียกใช้ฟังก์ชัน ใน main function เพื่อให้ตัวแปรภาษารู้ว่าฟังก์ชันนี้ทำงานอย่างไร 3) แม้ฟังก์ชันที่ใช้จะไม่มีค่าตัวแปรร่วม ก็ต้องใส่วงเล็บ [ ( ) ] ไว้หลังชื่อฟังก์ชันเสมอ 4) การกำหนดฟังก์ชัน จะต้องกำหนดก่อนการใช้ Main function เพื่อให้ Main function ได้รับรู้ว่าฟังก์ชันดังกล่าวมีอะไรเป็นตัวแปรร่วม และ จะคืนค่าอะไรออกมา 5) กลไกการทำงานเต็มของฟังก์ชันย่อยจะแสดงหลังจากที่เรียก Main function แล้ว หรืออยู่ในไฟล์ที่แยกต่างหาก ซึ่งจะมีการแปรออกมาแล้วเชื่อมต่อกับ Main function การกำหนดฟังก์ชันจะมีลักษณะดังนี้
float distance(float, float); // การกำหนดฟังก์ชัน [function prototype]

 void main()
 {
  float x0 = ….,y0 = …;
 float dist1 = distance(x0,y0); 
}
float distance(float x, float y) // float คือ ชนิดของฟังก์ชัน distance คือ ชื่อฟังก์ชัน
{    // float x, float y คือ บัญชีตัวแปรร่วม
 float dist;  // float dist คือ การประกาศตัวแปรเฉพาะที่;
 dist = sqrt(x*x+y*y); 
 return dist ;
}
ในการส่งผ่านตัวแปรเข้า ฟังก์ชัน (Passing argument) นั้นมีการเรียกได้ 2 แบบ คือ 1) ส่งผ่านตามค่า (Pass by Value) ซึ่งส่งผ่านค่า ลงในตัวแปรร่วมของฟังก์ชันโดยตรง 2) ส่งผ่านตามการอ้างอิง (pass by Reference) ซึ่งส่งผ่านค่า address ในหน่วยความจำของตัวแปร ให้กับตัวแปรร่วมของฟังก์ชัน ถ้ามีการเปลี่ยนแปลงข้อมูล ณ ตำแหน่งหน่วยความจำดังกล่าว ค่าที่ส่งให้ตัวแปรร่วมของฟังก์ชันก็จะเปลี่ยนด้วยตัวแปรที่เกี่ยวข้องกับฟังก์ชันคือ 1) ตัวแปรเฉพาะที่ (Local variables) เป็นตัวแปรที่อยู่และเปลี่ยนแปลงเฉพาะภายในฟังก์ชันที่เรียกใช้ตัวแปรดังกล่าว การเปลี่ยนแปลงภายนอกฟังก์ชันที่เรียกใช้ตัวแปรเฉพาะที่จะไม่มีผลต่อตัวแปรเฉพาะที่ดังกล่าว ดังตัวอย่างต่อไปนี้
void test_locvar(int num)
{
 int myvar; // Local variable fro this function
 myvar = num;
}
void main()
{
 int myvar, myvar_before, myvar_after; //Local variable for this function 
 myvar = 5;
 myvar_before = myvar; // myvar_before = 5;
 test_locvar(100); // call function
 myvar_after = myvar; // myvar_after = 5;
}
2) ตัวแปรส่วนกลาง (Global variables) เป็นตัวแปรที่อยู่นอกฟังก์ชันซึ่งสามารถเปลี่ยนแปลงค่าภายในตัวแปรได้ตลอดเวลาเมื่อตัวแปรได้รับการเปลี่ยนแปลงโดยฟังก์ชัน ดังตัวอย่างต่อไปนี้
int myvar; // Global varible
void test_locvar(int num)
{
 myvar = 20;
}

void main()
{
 int myvar_before, myvar_after;  //Local variable fro this function 
 myvar = 5;
 myvar_before = myvar; // myvar_before == 5;
 test_locvar(100); // call function
 myvar_after = myvar; // myvar_after == 20;
}
ฟังก์ชันมีหลายประเภทได้แก่ 1) ฟังก์ชันที่ไม่มี อาร์กิวเมนต์ และ ไม่คืนค่า เช่น ฟังก์ชัน void main() 2) ฟังก์ชันที่มี อาร์กิวเมนต์ แต่ ไม่คืนค่า เช่นฟังก์ชัน void do_something(float x, float y) ซึ่งจะทำงานตามที่ต้องการโดยอาศัยค่าอาร์กิวเมนต์ (ตัวแปร x,y) โดยไม่คืนค่าออกมา ฟังก์ชันดังกล่าวจะมีกลไกการับข้อมูลเข้าต่างหาก โดยไม่ต้องใช้ตัวแปรที่เป็น อาร์กิวเมนต์ 3) ฟังก์ชันที่ไม่มี อาร์กิวเมนต์ แต่ก็คืนค่า เช่น ฟังก์ชัน float do_something2() ค่าที่คืนมาได้จาก ตัวแปรเฉพาะที่และกลไกการคำนวณภายในฟังก์ชันดังกล่าว 4) ฟังก์ชันที่มี อาร์กิวเมนต์ และ คืนค่า เช่นฟังก์ชัน float distance(float x, float y) ฟังก์ชันดังกล่าว สามารถคืนค่า โดยไม่จำเป็นต้องใช้ตัวแปรเฉพาะที่ทำหน้าที่เป็นตัวแปรชั่วคราวในการคืนค่า ตัวอย่างเช่น
float distance3D(float x, float y, float z)
{
  return sqrt((x*x)+(y*y)+(z*z));
}


หน้าที่ 6 - อาเรย์ (Arrays)
5. ตารางอาเรย์ (Arrays) ตารางอาเรย์ เป็นตัวแปรสำหรับรวบรวมข้อมูลชนิดเดียวกัน ลงในตัวช่องรับข้อมูลที่ติดกันตั้งแต่ 2 ช่องขึ้นไป ซึ่งข้อมูลในตารางอาเรย์ดังกล่าวสามารถเข้าถึงได้ พร้อมกันหลายช่อง โดยใช้ตัวแปรตัวเดียวในการเข้าถึง การสร้างตารางอาเรย์ จะต้องมีการประกาศค่าตั้งต้นภายในตารางอาเรย์ที่จะใช้ดังต่อไปนี้
Type ArrayName[size];    // Format of Blank array 
Type ArrayNameInitialized[size] = {…};  // Format of initialized array 
int a[5] = {0,0,0,0,0};
double air[5];
char vowel[] = {’A’,’E’,’I’,’O’,’U’};
ในกรณีใช้ตัวแปรดัชนี้ชี้ตำแหน่งข้อมูลในตาราง ค่าของตัวแปรที่จะชี้จะต้องอยู่ในช่วงระหว่าง 0 กับ N-1 โดยที่ N คือขนาดตารางอาเรย์ ดังตัวอย่างที่แสดงในภาพที่ 5.1
5531
ถ้าค่าดัชนีน้อยกว่า 0 หรือมากกว่า N – 1 แล้วโปรแกรมจะทำงานผิดพลาดหรือหยุดทำงาน การแยกแยะช่องตาราง (Array subscription) ทำได้โดย การใช้ชื่อตัวแปรอาเรย์ ตามด้วย วงเล็บเหลี่ยมที่มีค่าดัชนี (เช่น Data[i], i = 0, 1, 2, … N-1 ) การประกาศค่าตั้งต้นให้ตัวแปรอาเรย์สามารถทำได้โดยใช้เครื่องหมายปีกกา ( { } ) หรือจะยกประกาศค่าตั้งต้นที่ละช่องตารางก็ได้ตามความต้องการของผู้ใช้ โดยส่วนที่ ไม่ได้ใส่ค่าตั้งต้นจะมีค่าเป็นศูนย์ (กรณีตารางอาเรย์แบบ int, double, หรือ float) หรือเป็นค่าว่าง ดังตัวอย่างต่อไปนี้
int a[4] = {9, 8, 7}; ซึ่งจะได้ค่าออกมาตรงกัย a[0] = 9; a[1] = 8; a[2] = 7; และ a[3] = 0;

 กรณีที่ตารางมีหลายมิติ จะมีการเรียกใช้ตามรูปแบบตารางมิติเดียวต่อไปนี้ 
ตาราง 2 มิติ: type arrayname2D[size1][size2];
ตาราง 3 มิติ: type arrayname3D[size01][size02][size03];

 การค้นข้อมูลในตารางอาเรย์นั้น สามารถเข้าถึงได้อย่างรวดเร็วไม่ว่าตารางจะใหญ่เพียงไหน เช่น

 const int SIZE = 100; // #define SIZE 100 for C
 float A[SIZE],B[SIZE],C[SIZE];
for(i = 0; i <= SIZE-1; i++)
 {
  C[i] = B[i] – A[i];
}
ในการใช้ตัวแปรอาเรย์เป็นอาร์กิวเมนต์ให้ฟังก์ชันนั้น แบ่งได้หลายกรณีได้แก่ 1) กรณีที่จะเอาข้อมูลเฉพาะช่องตาราง จะมีการส่งผ่านข้อมูลในตารางอาเรย์ดังนี้
void main()
{
float X[10], X[0] = 123.23, X[1] = 24.56, X[2] = 45.67; 
float total = sum_element(X[0],X[1],X[2]);
 … 
}
float sum_element(float A, float B, float C)
{
 return (A+B+C);
}
2) กรณีที่ใช้ข้อมูลทั้งตารางอาเรย์ การส่งผ่านข้อมูลในตารางลงในฟังก์ชันจะเป็นดังนี้
void main()
{
float X[10], X[0] = 123.23, X[1] = 24.56, X[2] = 45.67; 
float total = sum_element_array(X)
 … 
}
float sum_element_array(float A[])
{
 int index; float Sum = 0;
 for(index =0; index <= 3-1; index++)
{
  Sum +=A[index];
}
return Sum;
}
3) กรณีที่ใช้ข้อมูลทั้งตารางเพื่อให้ได้ผลลัพธ์ออกมาเป็นตารางอาเรย์ให้ทำดังนี้
void add_arrays(float ar1[],  // input array 1
  float ar2[],  // input array 2
  float ar_sum[],  // Output array
  int N)  // Array Size
{
 for(int i = 0; i <= N-1; i++)
 {
  ar_sum[i] = ar1[i] + ar[2];
}
}
การค้นหาข้อมูลในตาราง (Array searching) ในการค้นข้อมูลนั้นมักใช้ linear search หาข้อมูลในตารางตามที่ต้องการ โดยกำหนดเงื่อนไขว่า 1) ถ้าหาข้อมูลพบ ให้แสดงดัชนีของค่าที่ค้นพบ ก่อนออกจากวงรอบการค้นหา 2) ถ้าหาข้อมูลไม่พบ ให้ออกจากโปรแกรมแล้วคืนค่า ที่อยู่นอก ขอบเขต 0 – N-1, N คือ ขนาดตารางอาเรย์ (โดยมากให้คืนค่า -1) การสับเรียงข้อมูลในตาราง (Array Sorting) การสับเรียงข้อมูลมีหลายวิธี ซึ่งจะกล่าวถึงในที่นี้พอสังเขปดังนี้ 1) Bubble Sort ซึ่งเขียนใช้งานง่ายแต่ สับตำแหน่งข้อมูลได้ผลช้าที่สุด ซึ่งมีกลไกดังนี้
void BubbleSort(float list[], int N)
{
 int i,j;
 float temp;
 for(i = N-1; i>=0; i--)
 {
  for(j = 1; j <=i; j++)
  {
   if(list[j-1] > list[j])
   {
    temp = list[j-1];
    list[j-1] = list[j];
    list[j] = temp;
}
}

}
}
2) Selection Sort ซึ่งจะเลือกค่าที่ยังไม่ได้สับเปลี่ยนที่น้อยที่สุดเป็นหลัก ในการสลับที่
void SelectSort(float list[], int N)
{
 int i,j, MinIndex;
 float temp;
 for(i = 0; i<=N-2; i--)
 {
  MinIndex = I;
  
for(j = i+1; j <=N-1; j++)
  {
  
   if(list[j] < list[MinIndex])
   {
    minIndex = j 
} 
   
   temp = list[j-1];
   list[j-1] = list[j];
   list[j] = temp;
}
}
}
3) Insertion Sort ซึ่งจะเติมข้อมูลลงในตำแหน่งที่เหมาะสมในขั้นสุดท้าย ซึ่งจะต้องมีตัวแปรอาเรย์ อย่างน้อย 2 ตัว โดยที่อาเรย์ตัวแรกทำหน้าที่ เป็น List เก็บข้อมูล ต้นฉบับ (Source List) และอาเรย์ตัวหลังทำหน้าที่รับข้อมูลที่ผ่านการสับตำแหน่งแล้ว (Sorted List) ในการสับที่กันนั้น จะให้ข้อมูลปัจจุบันเคลื่อนผ่านข้อมูลที่ผ่านการสับตำแหน่งแล้ว จากนั้นจึงลงมือสลับข้อมูลอีกครั้งจนกว่าข้อมูลทั้งหมดจะเข้าที่
void insert_sort(float data[], int Size)
{
 int i,j;
 float DatElement;
 for(i=1;i<=Size-1;i++)
 {
  DatElement = data[i];
  j = i;
  while((j >= 1) && data[j-1] >DatElement)
  {
   data[j-1] = data[j];
   j = j-1;
}
data[j] = DatElement;
}
}


หน้าที่ 7 - ตัวแปรพอยเตอร์ (Pointers)
6. ตัวแปรพอยเตอร์ (Pointers) Pointer คือตัวแปรดัชนีที่ เก็บค่าตำแหน่งแอดเดรสของหน่วยความจำ ซึ่งตัวแปรพอยเตอร์นั้น จะมีเครื่องหมายดอกจันทร์ (*) นำหน้าเสมอ ดังตัวอย่างต่อไปนี้ int *Num; float *GreatNum; char *Name; ตัวแปรพอยเตอร์มีประโยชน์ในการลดปริมาณหน่วยความจำที่ต้องใช้ในการเขียนโปรแกรม โดยการส่งข้อมูลในรูปพอยเตอร์ เข้าไปในฟังก์ชันที่โปรแกรมเรียกพร้อมกันหลายฟังก์ชัน แทนการส่งข้อมูลในรูปตัวแปรธรรมดา ซึ่งต้องใช้ตัวแปรหลายตัว ตัวแปรพอยเตอร์มีลักษณะคล้ายตัวแปรตารางอาเรย์ แต่ที่แตกต่างกันคือ ตัวแปรตารางอาเรย์จะเก็บเฉพาะค่าต่างๆ ที่เป็นชนิดกันเดียวกับตัวแปรอาเรย์แต่ ตัวแปรพอยเตอร์จะเก็บเฉพาะค่าตำแหน่ง Address ตัวแปรเท่านั้น โดยไม่ได้มีการจัดเตรียมหน่วยความจำแบบไดนามิกส์ (Dynamic Memory Allocation) ไว้ การเข้าถึงตำแหน่งแอดเดรสทำได้โดย ใช้เครื่องหมายแอมเปอร์แซนด์ (&) ซึ่งจะแสดงให้เห็นดังตัวอย่างต่อไปนี้ ในที่นี้กำหนดให้ตัวแปร Andy อยู่ในตำแหน่ง Address ที่ 1776 ดังตังอย่างในภาพที่ 6.1
5533
Andy = 25; // Assigning Value 25 to Andy Fred = Andy; // Assigning Value 25 (Value of Andy) to Fred Ted = &Andy // Assigning Value 1776 (Address of Andy) to Ted via & อย่างไรก็ดี ถ้าต้องการให้ตัวแปร Ted สามารถ ดึงค่า จากตัวแปร Andy ได้ ให้ ใช้สัญลักษณ์ ตัวอ้างอิงโดยอ้อม (Indirect operand) ซึ่งเป็นนำเครื่องหมายดอกจันทร์ (*) นำหน้าตัวแปรที่เก็บค่าแอดเดรสตัวแปร ดังตัวอย่างในภาพที่ 6.2
5534
Beth = *Ted // Beth มีค่าเท่ากับ ค่าที่ตัวแปร Ted ชี้ซึ่งเท่ากับ 25 ตัวพอยเตอร์จะใช้กับตัวแปรชนิดใดก็ได้โดยที่ ตัวแปรพอยเตอร์ดังกล่าวจะได้รับการกำหนดหน่วยความจำตามลักษณะชนิดตัวแปรด้วย เช่น ตัวแปรพอยเตอร์ประเภท int จะได้รับการกำหนดหน่วยความจำไว้ที่ 4 ไบต์ ตัวอย่างการกำหนด ค่า Pointer จะแสดงให้เห็นดังนี้ โดยผลการกำหนดค่าจะแสดงให้เห็นในภาพที่ 6.3 สังเกตให้ดีจะพบว่า ตำแหน่งแอดเดรสหน่วยความจำเลื่อนไป 4ไบท์ ระหว่างตัวแปร j กับ k และ ตัวแปร k กับ ptr
5535
จากตัวแปรพอยเตอร์สู่ตัวแปรอาเรย์ (Pointer to Array) ตัวแปรอาเรย์มีความเกี่ยวข้องสัมพันธ์กับตัวแปรพอยเตอร์คือ ชื่อตัวแปรอาเรย์ (Array identifier) จะมีค่าเทียบได้กับตำแหน่งแอดเดรสของตารางช่องแรกซึ่งเทียบได้กับตำแหน่งแรก ตัวแปรพอยเตอร์ จะมีค่าเท่ากับแอดเดรสของตัวแปรแรกที่ตัวแปรพอยเตอร์ชี้ ดังตัวอย่างต่อไปนี้
int Num[20]; int *Ptr;

 การกำหนดค่าต่อไปนี้ถือว่าใช้ได้เหมือนกัน
 Ptr = Num; มีลักษณะเท่าเทียมกับ Ptr = &Num[0];
ความแตกต่างจะเกิดขึ้นเมื่อ มีการกำหนดค่าตัวต่อไป โดยที่เราสามารถกำหนดค่าแอดเดรสใหม่ให้ตัวแปร Ptr ได้ทันที ขณะที่ ตัวแปร Num จะชี้ไปที่ตำแหน่งแรกของตัวแปรจำนวนเต็ม ซึ่งมี 20 ตำแหน่งเสมอ ดังนั้น ตัวแปร Ptr จึงเป็นตัวแปรพอยเตอร์ที่เปลี่ยนตำแหน่งการชี้ได้ (Variable Pointer) ขณะที่ตัวแปร Num หรือชื่อตัวแปรอาเรย์เป็นตัวแปรพอยเตอร์ที่ตำแหน่งการชี้คงที่ตายตัว (Constant pointer) ดังตัวอย่างต่อไปนี้
int Num[20]; int *y; int *Ptr;
 Ptr = Num;
 *(Ptr+1) จะแสดงค่า Num[1];
 *(Ptr+i) จะแสดงค่า Num[i];
 y = &Num[0];
 y++;  // ตัวแปรนี้จะชี้ไปที่ Num[1] เท่านั้น
ตัวอย่างต่อไปนี้แสดงให้เห็นถึงการ ใช้ตัวแปรพอยเตอร์ชี้ไปที่ตัวแปรตารางอาเรย์ ซึ่งผลที่ได้จะแสดงให้เห็นในภาพที่ 6.4
5536
ให้ผู้อ่านลองเปลี่ยนคำสั่งในบรรทัด B เป็น printf(“ptr + d = %dn“”, i.*ptr++); ก่อนการทดสอบครั้งต่อไป เพื่อดูว่าโปรแกรมจะให้ผลออกออกมาผิดจากโปรแกรมเดิม เมื่อทดสอบแล้ว ให้ ลองแก้บรรทัด B อีกครั้งโดยแก้เป็น printf(“ptr + d = %dn“”, i.*(++ptr)); ในการกำหนดค่าให้ตารางอาเรย์แต่ละช่องโดยใช้ตัวแปรพอยเตอร์ นั้นทำได้โดยการใช้วงเล็บครอบตัวแปรอาเรย์ที่ตามด้วยเครื่องหมายบวกและตัวเลขแสดงดัชนีพร้อมใช้เครื่องหมายดอกจันทร์ (*) นำหน้า เนื่องจากวิธีดังกล่าวจะเหมือนกับการใช้เครื่องหมาย [] และเลขดัชนี เพื่อเข้าถึงข้อมูลในตัวแปรอาเรย์ดังตัวอย่างต่อไปนี้ *(array+5) = 50 จะมีค่าเทียบเท่ากับ array[5] = 50; ส่วนในการกำหนดและเปลี่ยนแปลงค่าโดยใช้ตัวแปรพอยเตอร์นั้นทำได้ดังโปรแกรมต่อไปนี้
void main(void)
{
 int i, j=1,k=2;
 int *ptr1, *ptr2; // Declare both variables as integer pointers
 float value[100], result[100];
 float *ptr3, *ptr4; // Declare both variables as integer pointers

 prt1 = &j;  // Defining ptr1 pointing to j 
ptr2 = &k;  // Defining ptr2 pointing to k
 ptr3 = value;  // ptr3 contain the address for the 1st element of value
 ptr4 = &value[0]; //  ptr4 contain the address for the 1st element of value

 // Value manipulation
*ptr1 = *ptr1+2  /* การบวกค่าที่ตัวแปรพอยเตอร์ ptr ชี้ไป อีก 2 */
*ptr2 = *ptr1  /* กำหนดให้ค่าที่ ตัวแปร ptr2 ชี้ เท่ากับค่าที่ตัวแปร prt1 ชี้ */
k = *ptr2  /* กำหนดให้ k มีค่าเท่ากับ ค่าที่ตัวแปร ptr2 ชี้ */ 
}
การเปลี่ยนแปลง ตัวแปรพอยเตอร์ด้วยวิธีการทางคณิตศาสตร์ สามารถทำได้ดังตัวอย่างต่อนี้
float *ptr3, *ptr4; float table[100];  float Pi = 3.1415927;
ptr3 = &table[0]; // กำหนดให้ ptr3 เก็บค่าตำแหน่งแอดเดรส ของตาราง table ช่องแรก
ptr3++; // เปลี่ยนค่าตำแหน่งแอดเดรส ใน ptr3 เป็นแอดเดรสตาราง table ช่องที่2 
*ptr3 = Pi;  // ข้อมูลช่องที่ 2 ของตาราง table มีค่าเท่ากับ Pi   
ptr3+=25;  // กำหนดให้ ptr3 ชี้ไปที่ตำแหน่งแอดเดรสตาราง table ช่องที่ 26 
*ptr3 = 2.2222;  // ข้อมูล ตาราง table ช่องที่ 26 มีคาเท่ากีบ 2.2222  

ptr3 = table;  // กำหนดให้ ptr3 ชี้ไปที่ table ช่องแรก
 for(int ii =0; ii < 100; ii++)
 {
  *ptr3++ = 37.0 // กำหนดให้ข้อมูลทุกช่องของ ตาราง table เท่ากับ 37 
}
ptr3 = &table[0]; //  ptr3 contain the address for the 1st element of value
ptr4 = &table[0]; //  ptr4 contain the address for the 1st element of value
ข้อพึงระมัดระวังคือ เครื่องหมาย ++ และ -– นั้นมีลำดับความสำคัญที่สูงกว่า * ดังนั้น *ptr++ มีค่าเท่ากับ *(ptr++) ซึ่งตัวแปรทั้ง 2 หมายถึงการเพิ่มตัวเลขตำแหน่ง แอดเดรส ไม่ใช้เพิ่มค่าที่ตัวพอยเตอร์ชี้ ส่วนกรณี *p++ = *q++ นั้น การกำหนดให้ค่าที่ตัวแปรพอยเตอร์ p มึค่าเท่ากับ ค่าที่ตัวแปรพอยเตอร์ q ชี้ จากน้นจึงมีการเลื่อนตำแหน่งแอดเดรสของตัวแปรพอยเตอร์ทั้ง 2 ไปอีก 1 ช่วง ดังตัวอย่างต่อไปนี้ *p = *q; p++; q++; ในการเตรียมพื้นที่ตารางแบบไดนามิกให้ตัวแปรพอยเตอร์นั้นทำได้ดังนี้ กรณี C: int *ptr; Ptr = (int *)malloc(6* sizeof(int)); กรณี C++: int *ptr; ptr = new int[6]; ส่วนการคืนหน่วยความจำเมื่อสิ้นสุดการทำงานของโปรแกรมทำได้ดังนี้ ซึ่งต้องทำทุกครั้งเมื่อใช้คำสั่งออกจากโปรแกรม มิฉะนั้นเครื่องคอมพิวเตอร์ จะเกิดอาการค้าง (Hang) เมื่อปิดโปรแกรมเพราะไม่ได้คืนหน่วยความจำอย่างที่ควรจะทำ กรณี C: free(ptr); กรณี C++: delete[] ptr; ตัวแปรพอยเตอร์และการเรียกฟังก์ชัน การเรียกฟังก์ชันมีหลายแบบ ได้แก่ 1) ฟังก์ชันที่ ไม่มีตัวแปรร่วมเป็นอาร์กิวเมนต์ และ ไม่คืนค่า (function with no parameter and no return value) ฟังกชันพวกนี้เพีบงแต่มีหน้าที่ทำงานอะไรบางอย่างตามที่ผู้เขียนโปรแกรมต้องการ เช่นกรณีฟังก์ชัน void skip3(void) เพื่อการกระโดดไปครั้งละ 3 บรรทัดเป็นต้น 2) ฟังก์ชันที่มีตัวแปรร่วมแต่ไม่คืนค่า ฟังก์ชันนี้จะทำงานตามค่าที่ตัวแปรร่วมกำหนด เช่นกรณีฟังก์ชัน void skip(int num) ซึ่งจะกระโดดครั้งละกี่บรรทัดตามจำนวนที่กำหนดลงในตัวแปร num 3) ฟังก์ชันที่ไม่มีตัวแปรร่วมแต่มีการคืนค่า ฟังก์ชันนี้มักจะให้ผู้ใช้โปรแกรมป้อนข้อมูลให้ฟังก์ชันจัดการประมวลผล ก่อนที่จะคืนค่าออกมา เช่นกรณีฟังก์ชัน float input(void) ที่จะคืนค่าหลังจากผู้ใช้โปรแกรมได้ป้อนข้อมูลให้ตามที่ฟังก์ชันสั่งให้ทำแล้ว 4) ฟังก์ชันที่มีตัวแปรร่วมและมีการ คืนค่า เช่นกรณีฟังก์ชัน float diff(float x, float y) ที่จะคืนค่าเป็นผลต่างระหว่างตัวแปร x และ ตัวแปร y ส่วนฟังก์ชันที่มีการใช้ตัวแปรร่วม นั้น มีวิธีการเรียกอยู่ 2 แบบคือ 1) กรณี เรียกตามค่า (Call by Value) กรณีนี้การเปลี่ยนค่าตัวแปรร่วมที่เกิดขึ้นในฟังก์ชัน จะไม่มีผลต่อ ค่าตัวแปรร่วมตั้งต้นดังตัวอย่างต่อไปนี้
void skipline(int num)
{
 int i ;
 for(i = 0 ; i <=num-1 ; i++)
 {
  printf(“n”);
}
num = 100;
}
void main(void)
{
 int num1 = 60;
 printf(“%d”,num1);
 skipline(num1) ;
}
กรณี เรียกตามค่านี้ ค่า num มีการเปลี่ยนแปลง แต่ไม่มีผลต่อค่า num1 ใน main function ตัวแปรร่วมในฟังก์ชันจะถือว่าเป็นกรณีเรียกตามค่า เมื่อการใช้ตัวแปรร่วมเป็นไปตามเงื่อนไขต่อไปนี้ • ตัวแปรร่วมนั้นแค่ส่งผ่านข้อมูลไปให้ฟังก์ชัน • ตัวแปรร่วมดังกล่าวจะไม่เป้นตัวแปรที่คืนค่าหลังสิ้นสุดการทำงานของฟังก์ชัน 2) กรณี เรียกตามการอ้างอิง (Call by Reference) ซึ่งต้องมีการเรียกใช้ตัวแปรพอยเตอร์กรณีนี้การเปลี่ยนค่าตัวแปรร่วมที่เกิดขึ้นในฟังก์ชัน จะมีผลต่อ ค่าตัวแปรร่วมตั้งต้นดังตัวอย่างต่อไปนี้
void flip(int *x, int *y)
{
 int temp;
 temp = *x;
 *x = *y;
 *y = temp; 
}
ในการเรียกใช้ฟังก์ชัน flip นั้น จะต้องเรียกจาก แอดเดรสตัวแปร ดังนี้ flip(&a,&b) มีบางกรณีที่มีการ เรียกตามค่าและเรียกตามการอ้างอิงในฟังก์ชันเดียวกันเช่นการแก้สมการกำลัง 2
bool quardsolve(float a, float b, float c, float *root1, float *root2)
{
 float disc = (b*b) – (4*a*c);
 if(disc < 0.0)
 {
  return false;
} 
else
{
 *root1 = (-b + sqrt(disc))/(2*a);
 *root2 = (-b – sqrt(disc))/(2*a);
 return true;
}
}
ตัวแปรดัชนี root1 และ root2 ทำหน้าที่เป็นตัวแปรร่วม Output ที่เรียกโดยการใช้อ้างอิง (Call by Reference) และ ตัวแปร a b c เป็นตัวแปรร่วม Input ที่ใช้กับการเรียกตามค่า (Call by Value) ถ้า การแก้สมการกำลัง 2 มีคำตอบให้คืนค่าเป็น true และ ค่า root1 และ root2 เป็นจำนวนจริง มิฉะนั้นให้ฟังก์ชันคืนค่า false ออกมาแทน เนื่องจาก ค่า root1 และ root2 นั้นได้รับการประกาศให้เป็น ตัวแปรร่วมอ้างอิง (Reference parameter) มีผลทำให้ฟังก์ชันต้นแบบ (Function Prototype) มีลักษณะเป็น bool quardsolve(float, float, float, float *, float *) เมื่อเรียกใช้งานฟังก์ชัน quardsolve ให้เรียกใช้งานฟังก์ชันดังนี้ float x1, y1; float test = quardsolve(1.0,2.0,1.0,&x,&y); ซึ่งการเรียกใช้ฟังก์ชันดังกล้าวคล้ายคลึงกับการเรียกใช้คำสั่ง scanf int number; scanf(“%d”, &number); ตัวอย่างการเรียกใช้ฟังก์ชันที่มีตัวแปรพอยเตอร์จะแสดงให้เห็นดังตัวอย่างต่อไปนี้ 1) ฟังก์ชันที่ มี ตัวแปรพอยเตอร์ที่แสดงในภาพที่ 6.5 นั้น จะอยู่ที่ฟังก์ชัน cal_cum โดยในฟังก์ชัน cal_sum มี ตัวแปร a และ b เป็น ตัวแปร input ขณะที่ตัวแปรพอยเตอร์ *r เป็นตัวแปร output เวลาเรียกใช้งานฟังก์ชัน cal_sum ในฟังก์ชัน main จะเรียกใช้งานดังนี้ double num1 = 2.4, num2 = 1.2,result; cal_cum(num1,num2,&result); แอดเดรสของตัวแปร result (&result) จะมีค่าเท่ากับชื่อตัวแปรพอยเตอร์ แม้ว่าตัวแปร result จะไม่ใช่ตัวแปรพอยเตอร์ก็ตาม 2) ฟังก์ชันที่มี ตัวแปรพอยเตอร์ที่แสดงในภาพที่ 6.6 นั้น จะอยู่ที่ฟังก์ชัน order ซึ่งใช้ตัวแปรพอยเตอร์ เป็น input และ output ทั้งคู่ ฟังก์ชัน order จะทำหน้าที่ จากเล็กไปหาใหญ่ โดยที่ ถ้า ค่าที่ตัวแปรพอยเตอร์ *small ชี้ขนาดใหญ่กว่าค่าที่ตัวแปรพอยเตอร์ *big ชี้ ให้ลงมือสับตำแหน่งการชี้ค่า
5537


หน้าที่ 8 - ตัวแปรสตริง
7. ตัวแปรสตริง (String) ตัวแปร string หรือแถวตารางอาเรย์ของตัวหนังสือนั้น ภาษา C ไม่มีกลไกที่จะสนับสนุนได้โดยตรง ถ้าต้องการให้ภาษา C สามารถรองรับข้อมูลที่เป็นตัวหนังสือแล้ว จะต้องมีการเตรียมพื้นที่หน่วยความจำให่เหมาะสมหรือการใช้สตริงค่าคงที่ (strong constant) ซึ่งจะทำให้โปรแกรมภาษา C เข้าถึงข้อมูลสตริงซึ่งจะเป็นทั้งข้อมูลที่เข้ามาในโปรแกรมและเปป็นข้อมูลที่ออกจากโปรแกรมได้ โดยทั่วไปแล้วโปรแกรมภาษา C จะสนับสนุนข้อมูลที่เป็นอักษรโดยกำหนดให้อักษรแต่ละตัว ในรูปแบบตัวแปรประเภท char และข้อมูลสตริงนั้นโปรแกรมที่เขียนด้วยภาษา C จะถือว่าเป็นชุดข้อมูลตัวหนังสือที่เรียงกันตามลำดับ ขณะที่โปรแกรมที่เขียนด้วยภาษา C++ จะถือว่าสตริงเป็นตารางอาเรย์ข้อมูลประเภทตัวหนังสือ (Array of char) โดยตัวหนังสือจะอยู่ในตารางแต่ละช่อง และ ณ ตำแหน่งสิ้นสุดของตารางอาเรย์ที่เก็บตัวแปรสตริงนั้นจะมีสัญลักษณ์ “{PBODY}” (ตัวสิ้นสุดสตริง หรือ ตัว NULL) บรรจุอยู่ ดังนั้น ในการเตรียมเนื้อที่สำหรับตัวแปรสตริงที่ประกอบด้วยตัวหนังสือ n ตัวนั้นจะต้องเตรียมตารางไดนามิกขนาด n+1 ช่องเสมอ ดังตัวอย่างต่อไปนี้ 1) ตัวหนังสือ ‘a’ เป็นตัวแปร char จะใช้เนื้อที่ 1 ไบต์ แต่ “a” เป็นตัวแปร string แล้ว จะต้องใช้เนื้อที่ขนาด 2 ไบต์เพื่อจุตัวอักษร ‘a’ และ ตัวสิ้นสุดสตริง ({PBODY}) 2) ตัวแปรสตริงสามารถประกาศให้อยู่ในรูปตารางต่อไปนี้ได้ a. ตารางอาเรย์ตัวหนังสือ char String1[10] สามารถรองรับตัวหนังสือได้มากที่สุด 9 ตัว และ ตัวสิ้นสุดสตริง b. ตัวแปรพอยเตอร์ตัวหนังสือ char *String2 สามารถรองนับตัวหนังสือได้ตามที่ผู้เขียนโปรแกรมได้เตรียมเนื้อที่ตารางไดนามิกส์ไว้ ถ้าต้องการทำอะไรกับตัวแปรสตริงแล้วให้เรียกใช้เฮดเดอร์ไฟล์ string.h ซึ่งเป็นไลบรารีไฟล์มาตรฐานสำหรับจัดการกับตัวแปรสตริง เราสามารถตั้งค่าเริ่มต้นให้ตัวแปรสตริงได้ 2 วิธีหลักคือ char S1[] = “Example”; ซึ่งภายในตัวแปรประกอบด้วย S1 |E|x|a|m|p|l|e|{PBODY}| ทั้งนี้เนื่องจากการเตรียมพื้นที่ขนาด 8 ช่องตาราง โดย 7 ช่องตารางแรกเก็บตัวหนังสือ และ ข้อมูลช่องสุดท้ายเก็บตัวสิ้นสุดสตริง char S2[20] = “Another Example”; ซึ่งภายในตัวแปรประกอบด้วย
S2            |A|n|o|t|h|e|r| |E|x|a|m|p|l|e|{PBODY}||?|?|?|?| 
ทั้งนี้เนื่องจากการเตรียมพื้นที่ขนาด 20 ช่องตาราง แต่ใช้จริง 16 ช่อง คือตัวหนังสือ 15 ช่องและ ช่องที่ 16 เก็บตัวสิ้นสุดสตริง การตั้งต้นตัวแปรสตริง ดังตัวอย่างต่อไปนี้ถือว่าเป็นการตั้งต้นตัวแปรสตริงที่ถูกต้อง
5538
ดังนั้น สิ่งที่เกี่ยวข้องสตริงสามารถสรุปออกมาได้ดังนี้ - ตัวแปรสตริงคือ ลำดับตัวหนังสือที่อยู่ภายในเครื่องหมายอัญประกาศ หรือเครื่องหมายคำพูด (“ ”) หรือ ตัวแปรสตริงคงที่ (String Constant) - อีกทางหนึ่งตัวแปรสตริงถือว่าเป็นตัวแปรตารางอาเรย์ ของตัวหนังสือ (Array of char) - สามารถใช้คำสั่ง printf scanf และ print ของภาษา C กับตัวแปรสตริงได้ - การประมวลเท็กซ์ คือการประมวลตัวแปรสตริง - หน่วยข้อมูลพื้นฐานของตัวแปรสตริงคือตัวหนังสือหรือ ชุดตัวหนังสือ ไมใช่ตัวเลข - การประยุกต์ใช้ตัวแปรสตริงนั้นคือ Word Processing หรือ Text Editor ตัวอย่างการใช้ตัวแปรสตริงจะแสดงให้เห็นดังนี้
#include  
void main()
{
 char first[100], last[100];
 int i;

 printf("nEnter your first name:");
 scanf("%s", first );
 printf("nEnter your last name:");
 scanf("%s", last );
 printf("nYour full name is: %s %sn", first, last );
 printf("First name is: ");
 for( i=0; (i<100 && first[i] != '{PBODY}') ; i++ ){
    printf("%c ",first[i]);
 }
 printf("nLast name is: ");
 for( i=0; (i<100 && last[i] != '{PBODY}') ; i++ ){
    printf("%c ",last[i]);
 }
 printf("n");
} 
ผลที่ได้การเขียนโปรแกรมเติมชื่อและนามสกุลจะแสดงให้เห็นในภาพที่ 7.1
5539
การใช้งานตัวแปรสตริงนั้นมีหลักการดังนี้ - เตรียมพื้นที่ตารางอาเรย์ให้ใหญ่พอรับตัวหนังสือแทนคำและ ตัวสิ้นสุดสตริงดังต่อไปนี้ char str1[6] = “Hello”; char str2[] = “Hello”; char *str3 = “Hello”; char str4[6] = {‘H’,’e’,’l’,’l’,’o’,’{PBODY}’}; ตัวแปรสตริงแต่ละตัวถือว่าเป็นตัวแปรคงที่ ดังนั้นจึง Assign ค่าแทนกันเช่นตัวอย่างต่อไปนี้ไม่ได้ Str1 = Str2; // ห้ามทำเช่นนี้กับตัวแปรสตริง เพราะมีวิธีอื่นที่ดีกว่านั้น ตัวอย่างต่อไปนี้แสดงให้เห็น วิธี Assign ตัวแปรสตริงโดยใช้ตัวแปรพอยเตอร์ เข้าช่วย char *S1 = “Hello”, *S2 = “Goodbye”; // ตัวแปร S1 และ S2 แก่ไขเปลี่ยนแปลงไม่ได้ char *S3; S3 = S1; // บังคับให้ S3 ชี้ไปที่ แอดเดรสของตัวแปรพอยเตอร์ S1 S3 = S2; // บังคับให้ S3 ชี้ไปที่ แอดเดรสของตัวแปรพอยเตอร์ S2 อีกตัวอย่างในการ Assign ตัวแปรสตริงสามารถแสดงให้เห็นดังนี้ char Str[6] = “Hello”; // ตั้งต้นตัวแปร Str ด้วยคำว่า Hellow char Str[0] = ‘Y’; char Str[4] = ‘{PBODY}’; // การแก้ไขให้ Str = “Yell” อย่างไรก็ตาม วิธีแก้ไขเปลี่ยนแปลงข้อมูลสตริงในตารางมีเงื่อนไขว่า - ตารางอาเรย์ที่ทำหน้าที่เป็นสตริงจะต้องปิดท้ายด้วย ‘{PBODY}’ เสมอ มิฉะนั้นตัวแปรอาเรย์ที่ทำหน้าที่เป็นสตริงจะไม่มีจุดสิ้นสุดสตริง - สตริงที่แก้ไขต้องมีขนาดน้อยกว่าขนาดของตารางอาเรย์ที่เก็บค่าสตริง การเปลี่ยนแปลงแก้ไขตัวแปรสตริงโดยใช้ไดนามิกอาเรย์นั้นต้องใช้ความระมัดระวังเป็นอย่างยิ่ง เพราะตารางไดนามิกส์นั้นต้องเตรียมพื้นที่ให้ ตัวสิ้นสุดสตริง (NULL) มิฉะนั้นโปรแกรมจะพิมพ์ข้อมูลสตริงออกมาผิดไปจากที่ต้องการ ดังตัวอย่างต่อไปนี้
char *s; 
 s = (char *)malloc(sizeof(char) * 0); // - WRONG, need to allocate 1 more space
 strcpy(s, "linux"); 
 printf("%sn", s);  
กรณีที่ใช้คำสั่ง strlen เพื่อหา ขนาดอาเรย์ก่อนทำ Dynamic allocation (malloc) นั้น พึงรับทราบว่า คำสั่ง strlen จะมีขนาดเพียงพอสำหรับตัวจำนวนอักษรที่ใช้ในตัวแปรสตริงเท่านั้น แต่ไม่ได้นับตัวแปร NULL ที่ใช้กำหนดจุดสิ้นสุดของสตริงด้วย โดยที่รายละเอียดเกี่ยวกับคำสั่ง strlen จะกล่าวถึงในตอนต่อไป การกำหนดค่าให้ตัวแปรสตริง (String Assignment) ตัวอย่างการกำหนดค่าให้ตัวแปรสตริง
char s[5]="SIIT";       // ใช้ได้, กำหนดค่าตัวแปรสตริงให้ตัวแปรอาเรย์
 char dept[5], *d=dept;  // ใช้ได้, กำหนดค่าตัวแปรสตริงให้ตัวแปรพอยเตอร์
 char name[20];
 name = “C. Sinthanayothin"; // ผิด อย่ากำหนดตัวแปรสตริงให้ตัวแปรอาเรย์ด้วยวิธีนี้
 strcpy(name,“C. Sinthanayothin"); // ใช้ได้, ให้ก๊อปปี้ค่าสตริงโดยใช้คำสั่ง strcpy  
 strcpy(dept,"IT");  // ใช้ได้, ก๊อปปี้ค่าสตริง ลงในตัวแปร dept
 printf("%s %s %sn",d,s,dept); // ใช้ได้, แสดงผลค่าสตริงด้ว printf
 d = strcpy(s,"EE");  // ใช้ได้, นี่คือการคืนค่าตัวแปรสตริง ลงใน ตัวแปร d ด้วยคำสั่ง strcpy
 printf("%s %s %s %sn",name,d,s,dept);

 char c1[30], c2[30]=“This is new c1 string”;
 char s[30] = "c programming "; 
 char str1[30];  // วิธี้ทำให้ตัวแปร str1 ไม่เป็น l-value เพราะเป็น constant array
 char *str; // วิธี้ทำให้ตัวแปร str เป็น l-value เพราะเป็น ตัวแปรพอยเตอร์ 
 strcpy(c1, c2);   // ใช้ได้, ก๊อปปี้ข้อมูลใน c2 ลงใน c1
 str = strcat(s,"is great!!"); // ใช้ได้, คือค่าเป็น ตัวแปรพอยเตอร์ประเภท char 
 str1 = strcat(s,"is great!!"); // ผิด, ฟังก์ชัน strcat ตอ้งคืนค่าด้วยตัวแปรพอยเตอร์ประเภท char ไม่ใช่ตารางอาเรย์ประเภท char
ข้อควรจำคือ: ต้องเตรียมพื้นที่หน่วยความจำไว้ให้พร้อมก่อนการกำหนดค่าให้ตัวแปรสตริงมิฉะนั้นอักษรบางตัวก็จะแหว่งหายไป ตัวแปรสตริงนั้นจะใช้ %s เป็นตัว place holder ขณะที่ใช้คำสั่ง sscanf ในการอ่านข้อมูลจำพวกสตริงแล้วจัดการแปลงข้อมูลให้อยู่รูปตามที่กำหนด ดังตัวอย่างต่อไปนี้
int sscanf( const char *buffer, const char *format [, argument ] ... ); 

char ch, int inum, float fnum; 
char buffer[100] = “A10 50.0”;
sscanf(buffer,”%c%d%f”,&ch,&inum,&fnum); /* puts ‘A’ in ch, 10 in inum and 50.0 in fnum */

sscanf("  85  96.2  hello","%d%.3lf%s",&num,&val,word);

// results: num=85, val = 96.2, word = "hello"
  ส่วน sprintf ใช้แสดงผลลัพธ์ที่อยู่ในรูปแบบต่างๆ ให้เป็นตัวแปรสตริงดังตัวอย่างต่อไปนี้
int sprintf( char *buffer, const char *format [, argument] ... );

char buffer[100];
sprintf(buffer,”%s, %s”,LastName,FirstName);
if (strlen(buffer) > 15)
  printf(“Long name %s %sn”,FirstName,LastName);
ถ้าต้องการแปลงตัวเลขให้เป็นข้อมูลสตริงให้ใช้ฟังก์ชัน sprintf และ ตัวแปรดัชนี้ char ทำตามคำสั่งต่อไปนี้
int sscanf(char *buffer, const char *format [, argument ] ... ); 
char S[10]; int day, month,year;
sprintf(S,”%d/%d/%d”, day, month, year);
ถ้า day = 23, month = 8, year = 2001 ผลลัพธ์คือ S = “23/8/2001”
ต่อไปนี้คือตัวอย่างการใช้ sprintf กับ sscanf เมื่อเปรียบเทียบกับ printf
#include 
#include 
int main()
{
 char s[30]="85  96.2  hello";
 int num, mon=8,day=23,year=2001;
 double val;
 char word[10];  // can we use: char *word;   
  // make sure your assign the proper address for pointer
 sscanf("  85  96.2  hello","%d%lf%s",&num,&val,word);
 printf("num=%d   val=%.3lf   word=%sn",num,val,word);
 sprintf(s,"%d/%d/%d", mon, day, year);
 printf("s = %sn",s);
 return 0;
}
ข้อทบทวน: ภาษาซี มีฟังก์ชันที่ใช้ดัดแปลงแก้ไขตัวแปรสตริง หลายแบบตามความต้องการของผู้ใช้ได้แก่: strlen(str) – คำนวณความยาวสตริง ซึ่งจะมีการนับไปเรื่อยๆ จนกว่าจะพบตัวแปร NULL ถึงจะหยุดโดยไม่มีการนับตัวแปร NULL ที่สิ้นสุดประโยคเข้าไปด้วย ดังตัวอย่างต่อไปนี้ int strlen(char *str); char str1 = “hello”; strlen(str1) จะคืนค่าออกเป็น 5 เพราะ มีอักษร 5 ตัว strcpy(dst,src) – ก็อปปี้ข้อมูลจากตัวแปรสตริง src พร้อมตัวสิ้นสุดสตริง NULL ไปที่ตัวแปรสตริง dst แต่มีเงื่อนไขว่าตัวแปร des ต้องได้รับการเตรียมพื้นที่ให้ใหญ่พอๆกับตัวแปร src และการเตรียมพื้นที่ ให้ ตัวแปร src และ ตัวแปร dst ต้องไม่ทับซ้อนกันมิฉะนั้นจะให้ผลที่คาดเดาไม่ได้ การประกาศใช้ฟังก์ชัน strcpy จะทำได้ดังนี้ char *strcpy(char *dst, char *src) strncpy(dst,src,n) – ก็อปปี้ข้อมูลจากตัวแปรสตริง src โดยไม่ก๊อปปี้ตัวสิ้นสุดสตริง NULL ไปที่ตัวแปรสตริง dst เนื่องจากมีจำนวนตัวอักษร n เป็นตัวจำกัดไว้ แต่มีเงื่อนไขว่าตัวแปร des ต้องได้รับการเตรียมพื้นที่ให้ใหญ่พอๆกับตัวแปร src และการเตรียมพื้นที่ ให้ ตัวแปร src และ ตัวแปร dst ต้องไม่ทับซ้อนกันมิฉะนั้นจะให้ผลที่คาดเดาไม่ได้ การประกาศใช้ฟังก์ชัน strncpy จะทำได้ดังนี้ char *strncpy(char *dst, char *src, int n) strcmp(str1,str2) – เปรียบเทียบข้อมูลในตัวแปร str1 กับข้อมูลในตัวแปรสตริง str2 โดยใช้อักษรตัวแรกที่เริ่มต่างกันเป็นหลักซึ่งให้ผลดังนี้ น้อยกว่า 0 -- ถ้าค่า ASCII ที่เริ่มแตกต่างใน str1 มีขนาดเล็กกว่า str2 หรือ str1 เริ่มต้นเหมือนกับ str2 แต่ str2 นั้นมีตัวอักษรมากกว่า มากกว่า 0 -- ถ้าค่า ASCII ที่เริ่มแตกต่างใน str1 มีขนาดใหญ่กว่า str2 หรือ str1 เริ่มต้นเหมือนกับ str2 แต่ str1 นั้นมีตัวอักษรมากกว่า 0 ถ้าตัวแปรสตริงทั้ง 2 ตัวนั้นใช้ตัวอักษรเดียวกันและความยาวเท่ากัน การประกาศใช้ฟังก์ชัน strcmp จะทำได้ดังตัวอย่างต่อไปนี้
int strcmp(char *str1, char *str2) 
#include 
#include 
void main()
{
 printf("%d n", strcmp("hello","hello")); // returns 0
 printf("%d n", strcmp("yello","hello")); //returns value > 0
 printf("%d n", strcmp("Hello","hello")); // returns value < 0
 printf("%d n", strcmp("hello","hello there")); // returns value < 0
 printf("%d n", strcmp("some diff","some dift")); //returns value<0
}
strncmp(str1,str2,n) – เปรียบเทียบข้อมูลในตัวแปร str1 กับข้อมูลในตัวแปรสตริง str2 เป็นจำนวนอักษร n ตัวโดยใช้อักษรตัวแรกที่เริ่มต่างกันเป็นหลัก และ จะมีการเปรียบเทียบในกรณีที่อักษรในตัวแปรมีจำนวนน้อยกว่า n การประกาศใช้ฟังก์ชัน strncmp จะทำได้ดังตัวอย่างต่อไปนี้ int strncmp(char *str1, char *str2,int n) ความแตกต่างระหว่าง strcmp และ strncmp จะแสดงให้เห็นดังตัวอย่างต่อไปนี้ strcmp(“some diff”,”some DIFF”) -- returns value > 0 strncmp(“some diff”,”some DIFF”,4) -- returns 0 strcat(str1,str2) – ใช้ในการนำข้อมูลในตัวแปร str2 ไปต่อท้ายตัวแปร str1 ซึ่งจะคืนค่าเป็น str1 ที่ได้รับการต่อให้ยาวขึ้น ตัวอย่างเช่น char *s1 = “C. “, *s3 = strcat(s1,“Sinthanayothin”); ผลลัพธ์: s1 = s3 = “C. Sinthanayothin” การประกาศใช้ฟังก์ชัน strcat จะทำได้ดังตัวอย่างต่อไปนี้ char* strcat(char *s1, const char* s2); strncat(str1,str2,n) – ใช้ในการนำข้อมูลในตัวแปร str2 จำนวน n อักษรไปต่อท้ายตัวแปร str1 ซึ่งจะคืนค่าเป็น str1 ที่ได้รับการต่อให้ยาวขึ้น ตัวอย่างเช่น char s1[10] = "IT "; char *s3 = strncat(s1,"050Basic",3); printf("%s n", s1); printf("%s n", s3); ผลลัพธ์: s1 = s3 = IT 050 การประกาศใช้ฟังก์ชัน strncat จะทำได้ดังตัวอย่างต่อไปนี้ char* strncat(char *s1, const char* s2ม int n); ฟังก์ชันเหล่านี้มีอยู่ในไลบรารีเฮดเดอร์ไฟล์ string.h ซึ่งต้องใช้คำสั่ง #include ถึงจะเรียกใช้ได้ เราสามารถสร้างตารางอาเรย์ให้ตัวแปรสตริง (Array of string) ดังตัวอย่างต่อไปนี้ char month[12][10] = {“January”, “February”, “March”, “April”, “May”, “June”, “July”, “August”, “September”, “October”, “November”, “December” }; แต่ถ้าต้องการให้ตารางอาเรย์สำหรับตัวแปรสตริง สามารถรองรับข้อมูลสตริงที่มีความยาวต่างกัน (Ragged array of string) ให้ดังนี้ char *MonthNames[13]; /* an array of 13 strings */ MonthNames[1] = “January”; /* String with 8 chars */ MonthNames[2] = “February”; /* String with 9 chars */ MonthNames[3] = “March”; /* String with 6 chars */ … ตัวอย่างตารางอาเรย์ให้ตัวแปรสตริงแสดงวันทั้ง 7 แบบ Ragged array of string จะแสดงให้เห็นในตัวอย่างต่อไปนี้
#include 
#include 
void main() 
{
  char *days[7]; char TheDay[10];int day;
  days[0] = "Sunday"; days[1] = "Monday";
  days[2] = "Tuesday"; days[3] = "Wednesday";
  days[4] = "Thursday"; days[5] = "Friday";
  days[6] = "Saturday";
  printf("Please enter a day: ");
  scanf("%9s",TheDay);
  day = 0;
  while ((day < 7) && (strcmp(TheDay,days[day])))
        day++;
  if (day < 7) printf("%s is day %d.n",TheDay, day);
  else printf("No day %s!n",TheDay);
} 
ในการรับและส่งข้อมูลจำพวกสตริงนั้นทำได้หลายวิธี ได้แก่ 1) ในกรณีที่ใช้คำสั่ง printf และ scanf นั้นให้ใช้ %s ในการอ่านข้อมูลและ แสดงข้อมูลสตริงออกมา 2) ใช้คำสั่ง gets ในการข้อมูลสตริงออกมาทีละบรรทัด ดังตัวอย่างต่อไปนี้ char name1[10], name2[30]; scanf(“%s”,name1); // Input: IT 050 gets(name2); // Input: C Programming printf(“Course is %sn”,name); // Output: IT 050 printf(“Detail is %sn”,name2); // C Programming
5540
การใช้งานคำสั่งกับตัวแปร อักษร (char operators) นี่คือตัวอย่างการใช้งานฟังก์ชันที่คุมการรับส่งข้อมูลตัวอักษร char ch; ch = getchar(); // Input ch – ใช้แทน scanf("%c",&ch); putchar(ch); // Output ch – ใช้แทน printf("Character is %cn",ch); ch = 'S'; // ใช้ได้ ตัวอย่างการกำหนดค่าตัวอักษรให้ตัวแปร char putchar(ch); // ผลที่ได้ออกมาคือ S putchar('T'); // ผลที่ได้ออกมาคือ T ฟังก์ชันที่ใช้กำหนดการทำงานให้ตัวแปร char ได้แก่ คำสั่ง: isalpha(ch); การใช้งาน: คืนค่าเป็น TRUE (จริง) ถ้า ch มีค่าในช่วง A-Z หรือ a-z ตัวอย่าง: c = isalpha(ch); // คืนค่า TRUE ถ้า ch=‘M’ และ คืนค่า FALSE ถ้า ch=‘5’ คำสั่ง: isdigit(ch); การใช้งาน: คืนค่าเป็น TRUE (จริง) ถ้า ch มีค่าในช่วง0-9 ตัวอย่าง: d = isdigit(ch); // คืนค่า FALSE ถ้า ch=‘M’ และคืนค่า TRUE ถ้า ch=‘5’ คำสั่ง: islower(ch); การใช้งาน: คืนค่าเป็น TRUE (จริง) ถ้า ch มีค่าในช่วง a-z ตัวอย่าง: c = islower(ch); // คืนค่า FALSE ถ้า ch=‘M’ return false, และคืนค่า TRUE ถ้า ch=‘m’ คำสั่ง: isupper(ch); การใช้งาน: คืนค่าเป็น TRUE (จริง) ถ้า ch มีค่าในช่วง A-Z ตัวอย่าง: c = isupper(ch); // คืนค่า TRUE ถ้า ch=‘M’ return false, และคืนค่า FALSE ถ้า ch=‘m’ คำสั่ง: isspace(ch); การใช้งาน: คืนค่า TRUE ถ้า ch คิอช่องว่างขาว (space, newline, tab ) ตัวอย่าง: c = isspace(ch); // คืนค่า TRUE ถ้า ch = ‘n’ คืนค่า FALSE ถ้า ch=‘m’ คำสั่ง: tolower(ch); การใช้งาน: คืนค่าตัวพิมพ์เล็กจากค่าอักษรในตัวแปร ch ถ้าเป็นไปได้ ตัวอย่าง: c = tolower(ch); // คืนค่า ‘m’ ให้ c ถ้า ch=‘M’ คำสั่ง: toupper(ch); การใช้งาน: คืนค่าตัวพิมพ์ใหญ่จากค่าอักษรในตัวแปร ch ถ้าเป็นไปได้ คำสั่ง: c = toupper(ch); // คืนค่า ‘M’ ให้ c ถ้า ch=‘m’
หน้าที่ 9 - โครงสร้างสตรักเจอร์
8. โครงสร้างสตรักเจอร์ (Structure) สตรักเจอร์ เป็นวิธีการเก็บตัวแปรหลากชนิดให้อยู่เป็นกลุ่มก้อนเดียวกัน ทำให้สามารถแยกโปรแกรมออกเป็นหน่วย (Modular Programming) ซึ่งแก้ไขได้ง่ายเพราะสามารถแยกฟังก์ชันและตัวแปรออกเป็นหน่วยๆ ซึ่งก็เป็นประโยชน์ในการสร้างฐานข้อมูลด้วย การตั้งต้นสร้างสตรักเจอร์ สามารถทำได้หลายรูปแบบดังตัวอย่างต่อไปนี้ 1) การใช้ คำสั่ง struct สร้างตัวแปรชนิด student_a ผ่านตัวแปร student struct student
{ 
   char *first; 
   char *last; 
   char SSN[9]; 
   float gpa; 
   char **classes; 
}; 
struct student student_a; 2) การใช้ คำสั่ง struct สร้างตัวแปรชนิด student_a โดยตรง struct
{ 
    char *first; 
    char *last; 
    char SSN[10]; 
    float gpa; 
    char **classes; 
} student_a; 
3) การใช้ คำสั่ง typedef struct เพื่อสร้างตัวแปรชนิด student_a ผ่านตัวแปร student typedef struct
{ 
    char *first; 
    char *last; 
    char SSN[9]; 
    float gpa; 
    char **classes; 
} student; 

student student_a;
การกำหนดชนิดตัวแปร ทำได้โดยใช้คำสั่ง typedef ตามหลักการใช้งานดังนี้ typedef type name (typedef ชื่อของชนิดตัวแปร ชื่อที่ใช้เรียกชนิดตัวแปรจริง) ตัวอย่าง:
typedef int INTEGER;
  INTEGER x;  /* x คือตัวแปรตระกูล INTEGER */

  typedef char *STRING;
  STRING sarray[10];  
/* sarray คือตารางอาเรย์ ของ char* ซึ่งเทียบได้กับการประกาศว่า 
char *sarray[10] */
ในโครงสร้างตัวแปรที่อยู่ในรูป structure นั้นประกอบด้วยตัวแปรที่เกี่ยวข้องในลักษณะเดียวกับตารางอาเรย์ แม้จะไม่ใช้ตัวแปรประเภทเดียวกัน โดยจะแบ่งตัวแปรออกเป็น field โดยที่กลุ่มตัวแปรใน structure จะถือว่าเป็นส่วนหนึ่งของหน่วยใหญ่หน่วยเดียวกันดังที่แสดงในภาพที่ 8.1 ส่วนการเปรียบเทียบความแตกต่างระหว่าง ตารางอาเรย์และตัวแปร struct ที่มีตัวแปรที่เป็นตารางอาเรย์ จะแสดงให้เห็นในภาพที่ 8.2
5542
การเรียกใช้งาน สตรักเจอร์ โดยปกติการสร้างสตรักเจอร์ ทำได้โดยใช้คำสั่ง typedef และ struct ซึ่งโครงสร้างภายในของสตรักเจอร์ จะประกอบด้วยตัวแปรต่างๆ ซึ่งแยกออกเป็น field ตัวแปรชนิดต่างๆ และในแต่ละ field จะมีการกำหนดพื้นที่หน่วยความจำ จนเพียงพอสำหรับแต่ละ field ดังตัวอย่างต่อไปนี้
typedef struct {
  Type1 FieldName1;
  Type2 FieldName2;
  Type3 FieldName3;
  /* as needed */
} VarName;
VarName คือชื่อชนิดตัวแปรสตรักเจอร์ทั้งหมด นี่คือตัวอย่างการประกาศใช้ตัวแปร struct ชนิด student_t เพื่อบันทึกข้อมูลนักเรียน พร้อมตัวอย่างการกำหนดตัวแปร ชนิด student_t ซึ่งสามารถทำได้อย่างตัวแปรทั่วไป เช่นเดียวกับ int float
#define   MAX_LEN  12      /*  Length of name  */
typedef   struct  {
   char      name[MAX_LEN];
   int      id;
   float     gpa;
   char major[10];
}  student_t;

student_t   s;
student_t  stu1, stu2, stu3;
การเข้าถึง ตัวแปร field ภายในตัวแปร struct ทำได้โดยการใช้ จุด (.)แล้วตามด้วยชื่อ field ดังตัวอย่างกรณีการเข้าถึงตัวแปร ชนิด DATE ที่จะแสดงให้เห็นดังต่อไปนี้ และผลที่ได้จะแสดงให้เห็นในภาพที่ 8.3 หลักการเข้าถึงตัวแปร struct: VarName.FieldName typedef struct
{
  int month, day, year;
} DATE;

void main() {
  DATE d1;

  d1.month = 12;
  d1.day = 2;
  d1.year = 1970;
}
5543
ขอขอบคุณข้อมูลดีๆจากเว็บ