Important Announcement
PubHTML5 Scheduled Server Maintenance on (GMT) Sunday, June 26th, 2:00 am - 8:00 am.
PubHTML5 site will be inoperative during the times indicated!

m

Published by milknoii2507, 2017-07-25 03:42:32

Description: m

Search

Read the Text Version

การเขียนโปรแกรมภาษา C เบือ้ งต้น(INTRODUCTION TO C PROGRAMMING)

พนื้ ฐานโปรแกรมภาษา Cดร. จนั ทร์จิรา สินทนะโยธิน, วศิ รุต พลสิทธิ สานกั งานพฒั นาวทิ ยาศาสตร์และเทคโนโลยีแห่งชาติ (สวทช) ฝึ กฝนและพฒั นาการเขยี นโปรแกรมภาษา C Introduction to CProgramming การพฒั นาโปรแกรมคอมพวิ เตอร์ บางคนกว็ า่ ยาก บางคนกว็ า่ เป็นเรื่องสนุกหลายคนบอกวา่ ขอเป็นแค่ผใู้ ชส้ นุกท่ีสุด แต่จะมีซกั ก่ีคนท่ีจะมีใจรักท่ีจะกา้ วไปบนถนนแห่งการพฒั นาฝีมือและฝึกฝนการเขียนโปรแกรมดว้ ยตวั เอง เพ่อื ใหม้ ีผทู้ ่ีสนใจนาไปใชง้ าน และเพ่ิมประสิทธ์ิภาพในการทางาน และ ความสะดวกสบายๆ ต่างๆมากข้ึน วา่ ไปแลว้ นกัโปรแกรมเมอร์เหล่าน้ี กไ็ ม่แตกต่างจากผทู้ ่ีปิ ดทองหลงั พระมากนกั เพราะหลายๆ โปรแกรมท่ีมีใหใ้ ชง้ านกนั ในปัจจุบนั จะมีใครทราบบา้ งไหมวา่ ผเู้ ขียนโปรแกรมเหล่าน้นั มีใครกนั บา้ ง ดงั น้นัผทู้ ่ีคิดจะกา้ วมาเป็นนกั พฒั นาโปรแกรมมืออาชีพ คงตอ้ งอาศยั ใจรักท่ีจะอยากจะพฒั นา และฝึกฝนฝืมือในการเป็นโปรแกมเมอร์มืออาชีพมาเป็นอนั ดบั หน่ึง สาหรับบทความน้ีจะเร่ิมตน้ ดว้ ยการสอนใหเ้ ขา้ ใจในหลกั การพ้นื ฐานของการการพฒั นาโปรแกรมในภาษา C ความรู้และความเขา้ ใจท่ีจาเป็นต่อการเป็นโปรแกรมเมอร์มืออาชีพในอนาคต เราลองเริ่มมาเรียนรู้กนั อยา่ งคร่าวๆกนั เลยล่ะกนั โดยผเู้ ขียนจะอธิบายเป็นตอนๆ ท้งั หมด 8 ตอนดว้ ยกนั ไดแ้ ก่ 1. พ้ืนฐานโปรแกรมภาษา C (Introduction to C Programming) 2. การเขียนโปรแกรมทางเลือก (SelectionStructures) 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 มาเขียนเป็นคาส่ังต่างๆ ท่ีคอมพวิ เตอร์สามารถเขา้ ใจได้ และกลุ่มของคาสงั่ เหล่าน้ี เรากเ็ รียกกนั วา่ อลั กอริธึม ไดม้ ีผใู้ หค้ าจากดั ความของคาวา่ อลั กอริธึม วา่ เป็น Aprecise description of a step-by-step process that is guaranteed to terminate after a finitenumber of steps with a correct answer for every particular instance of an algorithmic problemthat may occur.” สาหรบั Compiler ภาษา C ที่มีในปัจจุบนั มี 2 ค่ายใหญ่ๆ ท่ีมีผคู้ นสนใจใช้กนั มากไดแ้ ก่ Microsoft และ Borland การใชง้ าน Compiler ท้งั สองตวั น้ี สามารถเรียนรู้ไดไ้ ม่ยากนกั เราจึงจะมาเร่ิมตน้ ที่การเขียนโปรแกรมในภาษา C กนั เลย เราลองมาเริ่มจากตวั อยา่ งการเขียน ภาษา C แบบ ง่ายๆ กนั ก่อนกบั โปรแกรม Hello World #include main() { printf(\"HelloWorld!!!!! \"); } บรรทดั แรก #include เป็นการบอกวา่ ใหท้ าการรวม Header file ท่ีช่ือวา่ stdio.h(.h = header) ซ่ึงเป็น header ท่ีเกี่ยวขอ้ งกบั การรับและใหข้ อ้ มลู (Standard Input Output)นอกจาก stdio.h แลว้ กย็ งั มี Header อ่ืนๆ ที่ผพู้ ฒั นาสามารถที่จะเรียกใชง้ าน Function ที่จาเป็นจาก Header น้นั ๆ ได้ อาทิเช่น

รู้จกั 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]... );ตวั แปร (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;มาถึงตอนน้ี เรากจ็ ะสามารถปรับปรุงการเขียนโปรแกรมแบบง่ายๆ ไดด้ งั น้ี#includemain(){

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 Holdersprintf(\"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;

การให้กาหนดค่าตวั แปร (Variable Assignment) เราสามารถกาหนดค่าใหก้ บั ตวั แปรได้ ดว้ ยเคร่ืองหมาย = ยกตวั อยา่ งเช่น int name; // กาหนดตวั แปร name ที่เกบ็ ค่าจานวนเตม็ name = 23;// กาหนดใหต้ วั แปร name มีค่าเป็น 23 ในขณะเดียวกนั เราสามารถใชเ้ คร่ืองหมาย = ระหวา่ งตวัแปรกบั ตวั แปร หรือตวั แปรกบั จานวนใดๆ ได้ อาทิเช่นchange = x1 - x2;mean = (x1 + x2)/2;x = x + 1;ตอนน้ีเราลองมาเขียนโปรแกรมอยา่ งง่าย เพ่ือทาการแกป้ ัญหาทางคณิตศาสตร์ ดว้ ยการแปลงค่าอุณหภมู ิ ในหน่วยของ ฟาเรนไฮต์ เป็น เซลเซียส เม่ืออุณหภูมิในหน่วยฟาเรนไฮต์ มีค่า = 85และเป็นที่ทราบกนั ดีวา่ ความสมั พนั ธร์ ะหวา่ ง องศาฟาเรนไฮต์ และ เซลเซียส สามารถเขียนได้อยใู่ นรูปของสมการ

การเขียนโปรแกรม เพือ่ แกป้ ัญหา การแปลงค่า 85 ฟาเรนไฮตใ์ หเ้ ป็นเซลเซียส สามารถเขียนได้ดงั น้ี#includevoid main(){ float F; float C; F = 85; C = 5*(F-32)/9; printf(\"the result is %f\",C);}อีกตวั อยา่ ง ของโปรแกรม การบวกค่าจานวนเตม็ 2 จานวนเขา้ ดว้ ยกนั แลว้ แสดงผลลพั ธอ์ อกทางหนา้ จอ การเขียนโปรแกรมเพอ่ื แกป้ ัญหาน้ี สามารถเขียนไดด้ งั น้ี#includevoid 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 กนั วา่ จะเขียนกนั ไดอ้ ยา่ งไรบา้ งการเปรียบเทยี บ แบบมที างเลอื ก (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 มีดงั ต่อไปน้ี

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 แลว้ จะเห็นความแตกต่าง)

การเปรียบเทยี บตวั อกั ษร คุณผอู้ ่านทราบกนั หรือไม่วา่ ตวั อกั ษรสามารถเปรียบเทียบค่ากนั ได้เบ้ืองตน้ เราตอ้ งทราบก่อนวา่ ตวั อกั ษรมีค่าอยา่ งไรกนั บา้ ง  ตวั อกั ษรตวั เลก็ 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 4charactersn\"); 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);การเขยี นโปรแกรมแบบ วนซ้า (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);}ผลลพั ทท์ ่ีไดจ้ ะไดด้ งั น้ี 00 00 00 :: 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 positiveintegers: 532 112 The g.c.d. of 532 and 112 is 28 คราวน้ีเราลองมาดูการเขียนโปรแกรมเพ่ือแกป้ ัญหาดงั กล่าวขา้ งตน้ สามารถเขียนไดด้ งั น้ี#includevoid 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);}การดาเนินการทางคณิตศาสตร์ สามารถเขียนใหอ้ ยใู่ นรูปแบบส้ันๆ ได้ ดงั ตวั อยา่ งในตารางดงั น้ีความแตกต่างระหว่าง 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);}คราวน้ี เราลองมาทดลองเขียนโปรแกรม โดยใหโ้ ปรแกรม สามารถรับค่าตวั เลขใดๆ และแสดงค่าในรูปแบบดงั ตวั อยา่ งต่อไปน้ี

Input the number > 40010120123012010

เราสามารถแกป้ ัญหาขา้ งตน้ โดยใชโ้ ครงสร้างการเขียนโปรแกรมแบบวนซ้าดงั ต่อไปน้ี#includevoid 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 statementwhile ( เงื่อนไข ); ตวั อยา่ งของโครงสร้าง 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 ลงตวั#includevoid 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);}ตอนน้ีผอู้ ่านกค็ งจะรู้จกั การเขียนโปรแกรมแบบวนซ้ากนั แลว้ นะ ต่อไป เรากจ็ ะไปเรียนรู้เกี่ยวกบั การเขียนโปรแกรมแบบแยกเป็นโมดูลกนัฟังก์ชัน (Functions) และ โปรแกรมแยกเป็ นโมดูล (Modular Programming)4.ฟังก์ชัน และการเขยี นโปรแกรมแยกเป็ นโมดูล (Functions & ModularProgramming) สาหรับนกั พฒั นา ท่ีไดท้ าการพฒั นาโปรแกรมมามากๆ บางคร้ัง จาเป็นตอ้ งเขียนโปรแกรมท่ีมีขนาดใหญ่และมีความสลบั ซบั ซอ้ น จึงจาเป็นตอ้ งหาวธิ ีในการพฒั นาโปรแกรมที่ดี ซ่ึงสามารถทาไดด้ ว้ ยการ แตกปัญหาใหญ่ออกเป็นปัญหายอ่ ยๆ แลว้ แกป้ ัญหายอ่ ยออกไปที่ละส่วนจนกวา่ จะหมด ซ่ึงจะช่วยใหแ้ กป้ ัญหาใหญ่ๆ ไดส้ าเร็จนนั่ เอง ซ่ึงเราเรียกกนั วา่วธิ ีแบ่งแยกแลว้ พิชิต (Divide and Conquer) ซ่ึงจะเป็นแนวการแกป้ ัญหาแบบจากบนลงล่าง(Top down approach) ดงั แสดงใหเ้ ห็นดงั ภาพที่ 4.1

การแตกปัญหาออกเป็นฟังกช์ นั ยอ่ ยๆ มีขอ้ ดีดงั น้ี 1) การแยกปัญหาที่จะใชใ้ นการเขียนโปรแกรมออกเป็นฟังกช์ นั ยอ่ ยๆ จะช่วยใหเ้ ขียนโปรแกรมไดง้ ่ายข้ึนเพราะปัญหามีความซบั ซอ้ นนอ้ ยลง 2) การแยกปัญหาท่ีจะใชใ้ นการเขียนโปรแกรมออกเป็นฟังกช์ นั ยอ่ ยๆ สามารถแกป้ ัญหาตามที่โปรแกรมตอ้ งทา โดยมีโอกาสท่ีจะผดิ พลาดนอ้ ยลงเน่ืองจากไดท้ ดสอบแกไ้ ขขอ้ ผดิ พลาดภายในฟังกช์ นั ยอ่ ยๆ ก่อนรวมกนั เป็นโปรแกรมใหญ่แลว้ 3) การแยกปัญหาออกเป็นฟังกช์ นั ยอ่ ยน้นั มีประโยชน์ ที่ทาใหเ้ ราสามารถใชฟ้ ังกชนั ยอ่ ยๆ เหล่าน้ีกลบั ไปใชก้ บั โปรแกรมอื่นๆ ไดด้ ว้ ย 4) การนาฟังกชนั ยอ่ ยๆ เหล่าน้ีกลบั มาใชอ้ ีก จะช่วยลดขนาดของโปรแกรมลง และยงั ช่วยลดเวลาและค่าใชจ้ ่ายในการพฒั นาและการซ่อมบารุงโปรแกรมไดอ้ ีกดว้ ย เพราะไม่ตอ้ งเสียเวลาในการเขียนฟังกช์ นั ซ้า นอกจากฟังกช์ นั ยอ่ ยท่ียงั ไม่ไดเ้ ขียนมาก่อน ตวั อยา่ งการเขียนโปรแกรมออกเป็นโมดูลต่างๆ จะแสดงใหเ้ ป็นดงั ผงั ในภาพท่ี 4.2 ซ่ึงในภาพดงั กล่าวไดแ้ ยกโปรแกรม Main ออกเป็นส่วนๆ คือ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) การกาหนดฟังกช์ นั จะตอ้ งกาหนดก่อนการใช้ Mainfunction เพ่ือให้ 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) ตวั แปรเฉพาะที่ (Localvariables) เป็นตวั แปรท่ีอยแู่ ละเปลี่ยนแปลงเฉพาะภายในฟังกช์ นั ที่เรียกใชต้ วั แปรดงั กล่าว การเปล่ียนแปลงภายนอกฟังกช์ นั ที่เรียกใชต้ วั แปรเฉพาะที่จะไม่มีผลต่อตวั แปรเฉพาะที่ดงั กล่าว ดงัตวั อยา่ งต่อไปน้ี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 variblevoid 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) ฟังกช์ นั ท่ีไม่มี อาร์กิวเมนต์ และ ไม่คืนค่า เช่น ฟังกช์ นั voidmain() 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));}อาเรย์ (Arrays)5. ตารางอาเรย์ (Arrays) ตารางอาเรย์ เป็นตวั แปรสาหรับรวบรวมขอ้ มลู ชนิดเดียวกนั ลงในตวัช่องรับขอ้ มลู ที่ติดกนั ต้งั แต่ 2 ช่องข้ึนไป ซ่ึงขอ้ มูลในตารางอาเรยด์ งั กล่าวสามารถเขา้ ถึงได้พร้อมกนั หลายช่อง โดยใชต้ วั แปรตวั เดียวในการเขา้ ถึง การสร้างตารางอาเรย์ จะตอ้ งมีการประกาศค่าต้งั ตน้ ภายในตารางอาเรยท์ ่ีจะใชด้ งั ต่อไปน้ีType ArrayName[size]; // Format of Blank arrayType ArrayNameInitialized[size] = {…}; // Format of initialized arrayint a[5] = {0,0,0,0,0};double air[5];char vowel[] = {’ A’ ,’ E’ ,’ I’ ,’ O’ ,’ U’ };ในกรณีใชต้ วั แปรดชั น้ีช้ีตาแหน่งขอ้ มลู ในตาราง ค่าของตวั แปรท่ีจะช้ีจะตอ้ งอยใู่ นช่วงระหวา่ ง0 กบั N-1 โดยท่ี N คือขนาดตารางอาเรย์ ดงั ตวั อยา่ งท่ีแสดงในภาพท่ี 5.1

ถา้ ค่าดชั นีนอ้ ยกวา่ 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;}}ตวั แปรพอยเตอร์ (Pointers)

6. ตัวแปรพอยเตอร์ (Pointers) Pointer คือตวั แปรดชั นีที่ เกบ็ ค่าตาแหน่งแอดเดรสของหน่วยความจา ซ่ึงตวั แปรพอยเตอร์น้นั จะมีเครื่องหมายดอกจนั ทร์ (*) นาหนา้ เสมอ ดงั ตวั อยา่ งต่อไปน้ี int *Num; float *GreatNum; char *Name; ตวั แปรพอยเตอร์มีประโยชนใ์ นการลดปริมาณหน่วยความจาท่ีตอ้ งใชใ้ นการเขียนโปรแกรม โดยการส่งขอ้ มูลในรูปพอยเตอร์ เขา้ ไปในฟังกช์ นั ท่ีโปรแกรมเรียกพร้อมกนั หลายฟังกช์ นั แทนการส่งขอ้ มูลในรูปตวั แปรธรรมดา ซ่ึงตอ้ งใชต้ วั แปรหลายตวั ตวั แปรพอยเตอร์มีลกั ษณะคลา้ ยตวั แปรตารางอาเรย์ แต่ท่ีแตกต่างกนั คือตวั แปรตารางอาเรยจ์ ะเกบ็ เฉพาะค่าต่างๆ ที่เป็นชนิดกนั เดียวกบั ตวั แปรอาเรยแ์ ต่ ตวั แปรพอยเตอร์จะเกบ็ เฉพาะค่าตาแหน่ง Address ตวั แปรเท่าน้นั โดยไม่ไดม้ ีการจดั เตรียมหน่วยความจาแบบไดนามิกส์ (Dynamic Memory Allocation) ไว้ การเขา้ ถึงตาแหน่งแอดเดรสทาไดโ้ ดย ใช้เคร่ืองหมายแอมเปอร์แซนด์ (&) ซ่ึงจะแสดงใหเ้ ห็นดงั ตวั อยา่ งต่อไปน้ี ในท่ีน้ีกาหนดใหต้ วั แปรAndy อยใู่ นตาแหน่ง Address ที่ 1776 ดงั ตงั อยา่ งในภาพที่ 6.1

Andy = 25; // Assigning Value 25 to Andy Fred = Andy; // Assigning Value 25 (Value ofAndy) to Fred Ted = &Andy // Assigning Value 1776 (Address of Andy) to Ted via & อยา่ งไรกด็ ี ถา้ ตอ้ งการใหต้ วั แปร Ted สามารถ ดึงค่า จากตวั แปร Andy ได้ ให้ ใชส้ ญั ลกั ษณ์ ตวั อา้ งอิงโดยออ้ ม (Indirect operand) ซ่ึงเป็นนาเครื่องหมายดอกจนั ทร์ (*) นาหนา้ ตวั แปรท่ีเกบ็ ค่าแอดเดรสตวั แปร ดงั ตวั อยา่ งในภาพที่ 6.2Beth = *Ted // Beth มีค่าเท่ากบั ค่าท่ีตวั แปร Ted ช้ีซ่ึงเท่ากบั 25 ตวั พอยเตอร์จะใชก้ บั ตวั แปรชนิดใดกไ็ ดโ้ ดยท่ี ตวั แปรพอยเตอร์ดงั กล่าวจะไดร้ ับการกาหนดหน่วยความจาตามลกั ษณะชนิดตวั แปรดว้ ย เช่น ตวั แปรพอยเตอร์ประเภท int จะไดร้ ับการกาหนดหน่วยความจาไวท้ ี่ 4 ไบต์ตวั อยา่ งการกาหนด ค่า Pointer จะแสดงใหเ้ ห็นดงั น้ี โดยผลการกาหนดค่าจะแสดงใหเ้ ห็นในภาพที่ 6.3 สังเกตใหด้ ีจะพบวา่ ตาแหน่งแอดเดรสหน่วยความจาเล่ือนไป 4ไบท์ ระหวา่ งตวั แปรj กบั k และ ตวั แปร k กบั ptr

จากตัวแปรพอยเตอร์สู่ตัวแปรอาเรย์ (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ใหผ้ อู้ ่านลองเปล่ียนคาสัง่ ในบรรทดั 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 jptr2 = &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 มีค่าเท่ากบั Piptr3+=25; // กาหนดให้ ptr3 ช้ีไปที่ตาแหน่งแอดเดรสตาราง table ช่องท่ี 26*ptr3 = 2.2222; // ขอ้ มูล ตาราง table ช่องที่ 26 มีคาเท่ากีบ 2.2222ptr3 = 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 valueptr4 = &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 noreturn 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) มีบางกรณีท่ีมีการ เรียกตามค่าและเรียกตามการอา้ งอิงในฟังกช์ นั เดียวกนั เช่นการแกส้ มการกาลงั 2bool 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 byReference) และ ตวั แปร a b c เป็นตวั แปรร่วม Input ท่ีใชก้ บั การเรียกตามค่า (Call by Value) ถา้การแกส้ มการกาลงั 2 มีคาตอบใหค้ ืนค่าเป็น true และ ค่า root1 และ root2 เป็นจานวนจริงมิฉะน้นั ใหฟ้ ังกช์ นั คืนค่า false ออกมาแทน เน่ืองจาก ค่า root1 และ root2 น้นั ไดร้ ับการประกาศใหเ้ ป็น ตวั แปรร่วมอา้ งอิง (Reference parameter) มีผลทาใหฟ้ ังกช์ นั ตน้ แบบ (FunctionPrototype) มีลกั ษณะเป็น 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 ช้ี ใหล้ งมือสบั ตาแหน่งการช้ีค่าตัวแปรสตริง7. ตวั แปรสตริง (String) ตวั แปร string หรือแถวตารางอาเรยข์ องตวั หนงั สือน้นั ภาษา C ไม่มีกลไกที่จะสนบั สนุนไดโ้ ดยตรง ถา้ ตอ้ งการใหภ้ าษา C สามารถรองรับขอ้ มลู ที่เป็นตวั หนงั สือแลว้ จะตอ้ งมีการเตรียมพ้นื ที่หน่วยความจาให่เหมาะสมหรือการใชส้ ตริงค่าคงที่ (strongconstant) ซ่ึงจะทาใหโ้ ปรแกรมภาษา 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 เกบ็ ตวั สิ้นสุดสตริง การต้งั ตน้ ตวั แปรสตริง ดงั ตวั อยา่ งต่อไปน้ีถือว่าเป็นการต้งั ตน้ ตวัแปรสตริงที่ถกู ตอ้ ง

ดงั น้นั สิ่งท่ีเก่ียวขอ้ งสตริงสามารถสรุปออกมาไดด้ งั น้ี - ตวั แปรสตริงคือ ลาดบั ตวั หนงั สือที่อยู่ภายในเคร่ืองหมายอญั ประกาศ หรือเคร่ืองหมายคาพดู ( ) หรือ ตวั แปรสตริงคงท่ี (StringConstant) - อีกทางหน่ึงตวั แปรสตริงถือวา่ เป็นตวั แปรตารางอาเรย์ ของตวั หนงั สือ (Array ofchar) - สามารถใชค้ าสั่ง printf scanf และ print ของภาษา C กบั ตวั แปรสตริงได้ - การประมวลเทก็ ซ์ คือการประมวลตวั แปรสตริง - หน่วยขอ้ มูลพ้นื ฐานของตวั แปรสตริงคือตวั หนงั สือหรือชุดตวั หนงั สือ ไมใช่ตวั เลข - การประยกุ ตใ์ ชต้ วั แปรสตริงน้นั คือ Word Processing หรือ TextEditor ตวั อยา่ งการใชต้ วั แปรสตริงจะแสดงใหเ้ ห็นดงั น้ี#includevoid 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การใชง้ านตวั แปรสตริงน้นั มีหลกั การดงั น้ี - เตรียมพ้ืนที่ตารางอาเรยใ์ หใ้ หญ่พอรับตวั หนงั สือแทนคาและ ตวั สิ้นสุดสตริงดงั ต่อไปน้ี 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];


Like this book? You can publish your book online for free in a few minutes!
Create your own flipbook