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

ฝึกฝนและพัฒนาการเขียนโปรแกรมภาษา 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 นั้นๆ ได้ อาทิเช่น



รู้จัก 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;



การให้กำหนดค่าตัวแปร (Variable Assignment)

เราสามารถกำหนดค่าให้กับตัวแปรได้ ด้วยเครื่องหมาย = ยกตัวอย่างเช่น

int name; // กำหนดตัวแปร name ที่เก็บค่าจำนวนเต็ม
name = 23; // กำหนดให้ตัวแปร name มีค่าเป็น 23

ในขณะเดียวกัน เราสามารถใช้เครื่องหมาย = ระหว่างตัวแปรกับตัวแปร หรือตัวแปรกับจำนวนใดๆ ได้ อาทิเช่น

change = x1 - x2; mean = (x1 + x2)/2; x = x + 1;


ตอนนี้เราลองมาเขียนโปรแกรมอย่างง่าย เพื่อทำการแก้ปัญหาทางคณิตศาสตร์ ด้วยการแปลงค่า อุณหภูมิ ในหน่วยของ ฟาเรนไฮต์ เป็น เซลเซียส เมื่ออุณหภูมิในหน่วยฟาเรนไฮต์ มีค่า = 85 และเป็นที่ทราบกันดีว่า ความสัมพันธ์ระหว่าง องศาฟาเรนไฮต์ และ เซลเซียส สามารถเขียนได้อยู่ในรูปของสมการ



การเขียนโปรแกรม เพื่อแก้ปัญหา การแปลงค่า 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 กันว่าจะเขียนกันได้อย่างไรบ้าง




หน้าที่ 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 มีดังต่อไปนี้



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 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); }


การดำเนินการทางคณิตศาสตร์ สามารถเขียนให้อยู่ในรูปแบบสั้นๆ ได้ ดังตัวอย่างในตารางดังนี้



ความแตกต่างระหว่าง 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 > 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



การแตกปัญหาออกเป็นฟังก์ชันย่อยๆ มีข้อดีดังนี้
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) การกำหนดฟังก์ชัน จะต้องกำหนดก่อนการใช้ 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



ถ้าค่าดัชนีน้อยกว่า 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; } }

ไม่มีความคิดเห็น:

แสดงความคิดเห็น