การเขียนโปรแกรมแบบ วนซ้ำ (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 %d ",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(%d ,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 %d ", 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 = %d ,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 = %d ,count); } for ( count=10 ; count > 5 ; count -= 2) // ตัวแปร count มีค่าเปลี่ยนแปลงลดลงครั้งละ 2 { printf(count = %d ,count); }
นอกจากนี้เรายังสามารถใช้ตัวแปร เป็นการกำหนด ค่าเริ่มต้น เงื่อนไข และ เปลี่ยนแปลงได้ ยกตัวอย่างเช่น
start = 0; end = 20; step=3; for ( count=start ; count < end ; count += step) { printf(count = %d ,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(" "); } for(j= number-1; j>= 0; j--) { for(i=0; i< j; i++) { printf("%d ", i); } printf(" "); } }
โครงสร้างการเขียนโปรแกรมแบบวนซ้ำโดยใช้คำสั่ง 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 number "); scanf("%d", &number); i = 0; do { if((i % 4) == 0) printf("%d ", i); i++; } while(i <= number); }
ตอนนี้ผู้อ่านก็คงจะรู้จัก การเขียนโปรแกรมแบบวนซ้ำกันแล้วนะ ต่อไป เราก็จะไปเรียนรู้เกี่ยวกับการเขียนโปรแกรมแบบแยกเป็นโมดูลกัน
-------------------------------------------------------
คำสั่งในกลุ่มนี้ เป็นอีกกลุ่มหนึ่งที่คุณจะต้องใช้งานบ่อยครั้งที่สุด ไม่ว่าคุณจะพัฒนาแอพพลิเคชันด้วยภาษาอะไรก็ตาม เพราะมีหน้าที่สำหรับสั่งให้ VB ประมวลผลซ้ำกลุ่มคำสั่งเดิม วนไปเรื่อยๆ จนกว่าจะตรงกับเงื่อนไข ที่คุณต้องการ และยังมีหน้าที่สำหรับลดขั้นตอนในการเขียนโค้ดที่มีลักษณะเหมือนๆ กันได้อีกด้วย
For-Next
Do While-Loop
Do-Loop While
Do Until-Loop
Do-Loop Until
การวนลูปแต่ละชนิด มีรายละเอียดดังนี้
คำสั่ง For-Next
คำสั่งนี้ มีหน้าที่สำหรับสั่งให้ VB วนลูป เหมาะสมกับการทำงาน ที่คุณทราบจำนวนรอบ หรือทราบขอบเขตการวนที่แน่นอน มีรูปแบบการใช้งานดังนี้
For counter = start To end [Step step ]
statements
[Exit For]
[statements ]
Next [counter ]
ตัวแปร counter หมายถึง ตัวแปรที่คุณกำหนดขึ้นมาเพื่อ เป็นตัวนับรอบที่ใช้ในการวนลูป
ตัวแปร start หมายถึง ค่าเริ่มต้นของตัวนับ เป็นเลขจำนวนจริง คุณควรที่จะใช้เลขจำนวนเต็มเท่านั้น เพื่อง่ายต่อการตรวจสอบค่าตัวนับ
คำสงวน To หมายถึง ขอบเขตการนับ
ตัวแปร end หมายถึง ค่าสิ้นสุดของตัวนับ ไม่จำเป็นต้องเป็นตัวเลข ในบางครั้งคุณอาจสร้างเป็นเงื่อนไขที่ไม่ใช่ตัวเลขก็ได้ แต่ในการใช้งานโดยทั่วๆ ไป จะเป็นตัวเลข และควรจะเป็นเลขจำนวนเต็มด้วย
คำสงวน Step หมายถึง เป็นการกำหนดค่าที่จะเพิ่มขึ้นของตัวนับในแต่ละรอบ ถ้าคุณไม่กำหนด จะเพิ่มรอบละ 1
ตัวแปร step หมายถึง ค่าของตัวนับที่จะเพิ่มขึ้นในแต่ละรอบ จะต้องเป็นเลขจำนวนจริงเท่านั้น ในการใช้งานตามปกติ คุณควรใช้เลขจำนวนเต็ม เพื่อง่ายต่อการตรวจสอบจำนวนรอบในภายหลัง
ตัวแปร statements หมายถึง ชุดคำสั่งที่คุณต้องการวนลูป
คำสั่ง Exit For หมายถึง คำสั่งที่บังคับให้ออกจากลูปทันที จะใช้ในบางกรณีเท่านั้น เช่นการดักจับข้อผิดพลาด
note.gif (1525 bytes) สาเหตุที่ผู้เขียนแนะนำให้คุณกำหนดค่าตัวนับ หรือตัวสิ้นสุด เป็นเลขจำนวนเต็ม เพราะเนื่องจากว่า ถ้าคุณเคยทดสอบ การประมวลผลเครื่องคอมพิวเตอร์ ด้วยโปรแกรม Benchmark, Wintune 99, หรือ FPU WinMark ฯลฯ ตามมาตรฐาน iComp Index 1.0, 2.0 หรือ 3.0 คุณจะพบว่า ไม่ว่าคุณจะใช้ CPU ยี่ห้อใดก็ตาม การประมวลผลแบบ ทศนิยมจะช้ากว่า การประมวลผลแบบเลขจำนวนเต็มอยู่พอสมควร ซึ่งจะส่งผลเป็นอย่างยิ่ง ในกรณีที่คุณมีการสั่งวนรอบหลายหมื่น หรือแสนรอบ รวมถึงการสั่งให้เข้าถึงข้อมูลในแต่ละ record ในฐานข้อมูลที่มี records จำนวนมากๆ แอพพลิเคชันจะประมวลผลช้ามาก คุณควรให้น้ำหนัก ในเรื่องรายละเอียดปลีกย่อยนี้ พอสมควรครับ :-) ด้วยเหตุนี้เอง คุณควรที่จะใช้ข้อมูลชนิดที่เป็นเลขจำนวนเต็ม ไม่ว่าจะเป็น Integer หรือ Long ให้มากที่สุด เท่าที่จะเป็นไปได้ และข้อให้ใช้ชนิดข้อมูลที่เป็นพื้นฐานให้มากที่สุด ซึ่งยังเป็นการประหยัดทรัพยากรระบบอีกทางหนึ่งด้วย
สำหรับตัวอย่างการใช้งานคำสั่ง For-Next มีดังนี้
Private Sub Form_Activate()
Dim i As Integer
For i = 1 To 10
Print i
Next i
End Sub
ตัวอย่างดังกล่าว เป็นการพิมพ์เลขตั้งแต่ 1-10 ลงบนฟอร์ม ให้คุณลองเปลี่ยน step จาก 1 เป็น 2 แล้วสังเกตผล
คำสั่ง Do While-Loop
เป็นคำสั่งทำซ้ำ ที่มีจำนวนรอบขึ้นอยู่กับเงื่อนไข
Do While condition
statements
[Exit Do]
Loop
ตัวแปร condition หมายถึง เงื่อนไขที่คุณกำหนดขึ้นมา
ตัวแปร statements หมายถึง ชุดคำสั่งที่คุณต้องการทำซ้ำ
คำสั่ง Exit Do หมายถึง ออกจาก Do While-Loop ทันที
คำสั่ง Loop หมายถึง ขอบเขตสิ้นสุดการวนลูป
ลูปแบบ Do While นี้ จะวนลูปก็ต่อเมื่อเงื่อนไข (ตัวแปร condition) ยังเป็นจริงอยู่ ถ้าเงื่อนไขดังกล่าวเป็นเท็จเมื่อใด ก็จะออกจากลูปทันที มีข้อที่น่าสังเกตคือ การใช้ ลูปแบบนี้ จะมีโอกาสที่ไม่ต้องวนลูปเลยแม้แต่รอบเดียว นั่นคือ ถ้าเงื่อนไขที่เข้ามาเป็นเท็จ ก็ไม่ต้องวนทันที เช่น
Private Sub Form_Activate()
Dim i As Integer
Do While i <= 10
Print i
i = i + 1
Loop
End Sub
ตัวอย่างด้านบน จะมีผลเหมือนกับลูป For-Next เพียงแต่เปลี่ยนลักษณะวนลูป และเงื่อนไข ลองเปลี่ยนเงื่อนไข ดังนี้
Private Sub Form_Activate()
Dim i As Integer
i = 11
Do While i <= 10
Print i
i = i + 1
Loop
End Sub
จะเห็นได้ว่า บนฟอร์มไม่มีการพิมพ์เลข แต่อย่างใด เพราะตัวแปร i มีค่าเท่ากับ 11 ส่งผลให้เงื่อนไขเป็นเท็จทันที
คำสั่ง Do-Loop While
คำสั่งนี้เป็นการสั่งวนลูป มีจำนวนรอบขึ้นอยู่กับเงื่อนไข มีรูปแบบการใช้งานดังนี้
Do
statements
[Exit Do]
Loop While condition
ตัวแปร condition หมายถึง เงื่อนไขที่คุณกำหนดขึ้นมา
ตัวแปร statements หมายถึง ชุดคำสั่งที่คุณต้องการทำซ้ำ
คำสั่ง Exit Do หมายถึง ออกจาก Do- Loop While ทันที
คำสั่ง Loop หมายถึง ขอบเขตสิ้นสุดการวนลูป
จะเห็นได้ว่า มีลักษณะคล้ายกับแบบที่ 1 เพียงแต่ย้ายเงื่อนไขมาไว้ด้านล่าง ซึ่งหมายความว่า ลูปแบบนี้จะวนอย่างน้อยที่สุด 1 รอบ เพื่อตรวจสอบเงื่อนไข (ตัวแปร condition) ในรอบแรกที่เข้ามาก่อนว่าเป็นจริง หรือเท็จ ถ้าจริงก็จะวนลูปต่อไปตามปกติ แต่ถ้าเป็นเท็จ จะออกจากลูปทันที เช่น
Private Sub Form_Activate()
Dim i As Integer
Do
Print i
i = i + 1
Loop While i <= 10
End Sub
เช่นกัน ตัวอย่างนี้ เป็นการพิมพ์เลขตั้งแต่ 1 ถึง 10 บนฟอร์ม ให้คุณลองเปลี่ยนเงื่อนไขดังนี้
Private Sub Form_Activate()
Dim i As Integer
i = 11
Do
Print i
i = i + 1
Loop While i <= 10
End Sub
ข้อแตกต่างของลูป Do While – Loop กับ Do-Loop While นั่นคือ ถ้าเป็น Do While-Loop กรณีที่เงื่อนไขเป็นเท็จ บนฟอร์ม จะไม่ปรากฏตัวเลขอะไรเลย เพราะเนื่องจากว่า ไม่ได้มีการวนลูปแต่อย่างใด เพราะเงื่อนไขเป็นเท็จ (ค่า i=11) แต่ลูปแบบ Do-Loop While จะปรากฎค่าของตัวเงื่อนไขออกมาก่อน ถ้าจริง ก็จะวนลูปตามปกติ แต่กรณีนี้เป็นเท็จ จึงแสดงค่าออกมา 1 ค่า ซึ่งเกิดมาจาก การวนรอบแรกนั่นเอง
คำสั่ง Do Until-Loop
คำสั่งนี้มีหน้าที่สั่งให้วนลูปเช่นกัน มีจำนวนรอบขึ้นอยู่กับเงื่อนไข (condition) ถ้าเงื่อนไขเป็นเท็จ จึงจะวนลูป แต่ถ้าเป็นจริงจะไม่มีการวนแต่อย่างใด ซึ่งจะตรงกันข้ามกับลูปชนิด Do While-Loop มีรูปแบบการใช้งานดังนี้
Do Until condition
statements
[Exit Do]
statements
Loop
ตัวแปร condition หมายถึง เงื่อนไขที่คุณกำหนดขึ้นมา
ตัวแปร statements หมายถึง ชุดคำสั่งที่คุณต้องการทำซ้ำ
คำสั่ง Exit Do หมายถึง ออกจาก Do Until- Loop ทันที
คำสั่ง Loop หมายถึง ขอบเขตสิ้นสุดการวนลูป เช่น
Private Sub Command1_Click()
Dim x As Integer
Do Until x >= 10
Print x
x = x + 1
Loop
End Sub
ตัวอย่างนี้เป็นการพิมพ์เลข 1 ถึง 10 ลงบนฟอร์ม ทุกๆ ครั้งที่มีการคลิ๊กที่ปุ่ม Command1
คำสั่ง Do-Loop Until
คำสั่งการวนลูปแบบนี้มีลักษณะคล้ายกับลูปแบบ Do-Loop While เพียงแต่ เงื่อนไขที่เข้ามาจะต้องเป็นเท็จ จึงจะวนลูป ถ้าเงื่อนไขเป็นจริง จะออกจากลูปทันที การใช้ลูปแบบนี้จะมีการวนอย่างน้อยที่สุด 1 รอบเช่นกัน เนื่องจากการวนรอบแรก ที่จะต้องมีการตรวจสอบเงื่อนไขนั่นเอง มีรูปแบบการใช้งานดังนี้
Do
statements
[Exit Do]
[statements ]
Loop Until condition
ตัวแปร condition หมายถึง เงื่อนไขที่คุณกำหนดขึ้นมา
ตัวแปร statements หมายถึง ชุดคำสั่งที่คุณต้องการทำซ้ำ
คำสั่ง Exit Do หมายถึง ออกจาก Do Loop-Until ทันที
คำสั่ง Loop หมายถึง ขอบเขตสิ้นสุดการวนลูป เช่น
Private Sub Command1_Click()
Dim x As Integer
x = 11
Do
Print x
x = x + 1
Loop Until x >= 10
End Sub
จากตัวอย่างนี้ จะเห็นได้ว่า ค่า x=11 ซึ่งถึงแม้ว่า จะทำให้เงื่อนไขเป็นจริง (ออกจากลูป) ก็ตาม แต่ฟอร์ม ก็ยังคงพิมพ์ค่า x ออกมา 1 ค่า เนื่องจาก การวนรอบแรกนั่นเอง
note.gif (1525 bytes) ข้อควรระวังไม่ว่าคุณจะใช้ลูปแบบใดก็ตาม ในกรณีที่คุณประกาศตัวนับ เป็นเลขจำนวนเต็มชนิด Integer ขอให้คุณระวังเกี่ยวกับจำนวนรอบ ในการวนให้ดี เพราะเนื่องจากว่า ขอบเขตของข้อมูลขนิด Integer มีค่าระหว่าง -32768 ถึง 32767 ซึ่งถ้าคุณใช้แต่ค่าบวก จะทำให้ตัวแปรดังกล่าว สามารถวนได้เพียง 32768 รอบเท่านั้น ซึ่งจะมีผลในตอนรัน ถ้ามีโอกาสที่ทำให้เกิดการวนมากกว่า 32768 รอบ ก็จะเกิด error ได้ ซึ่งเป็นเหตุการณ์ที่ผู้เขียนพบโดยบังเอิญ
0 comments:
Post a Comment