การควบคุมลำดับคำสั่ง (Control Structure )
ภาษา C++ มีการควบคุมลำดับคำสั่งของโปรแกรมเช่นเดียวกับภาษาคอมพิวเตอร์อื่น ๆ มีรายละเอียด ดังนี้
- การควบคุมโดยใช้เงื่อนไข (if, else)
- การวนรอบ ( while, do while)
- การวนรอบ โดยใช้ for
- การเลือกทำคำสั่งจากชุดคำสั่งหลาย ๆ ชุด (switch)
- ตัวอย่างการนำ control structure เขียนโปรแกรมคำนวณทางคณิตศาสตร์ง่าย ๆ
ประโยค if ใช้ในการควบคุมการทำงานของโปรแกรม ให้เป็นไปตามเงื่อนไขที่กำหนดไว้
รูปแบบการใช้ if แบบที่ 1
if (conditional_expression) {
ชุดคำสั่งที่ 1(statements 1);}
ชุดคำสั่งที่ 2 (statements 2);
ถ้าประโยคเงื่อนไข conditional_expression เป็นจริง คำสั่งชุดที่ 1 ภายในวงเล็บปีกกาจะทำงาน แล้วจึงออกจากวงเล็บมาทำคำสั่งชุดที่ 2 ถ้า conditional_expression เป็นเท็จ โปรแกรมจะข้ามมาทำชุดคำสั่งที่ 2
รูปแบบการใช้ if แบบที่ 2
if (conditional_expression) {
ชุดคำสั่งที่ 1;} else {
ชุดคำสั่งที่ 2 ;}
ชุดคำสั่งที่ 3;
ถ้าประโยคเงื่อนไข conditional_expression เป็นจริง โปรแกรมจะทำ คำสั่งชุดที่ 1 ภายในวงเล็บปีกกาจากนั้นจะกระโดดข้ามมาทำชุดคำสั่งที่ 3 ถ้า conditional_expression เป็นเท็จ โปรแกรมจะทำชุดคำสั่งที่ 2 แล้วต่อด้วยชุดคำสั่งที่ 3
รูปแบบการใช้ if แบบที่ 3
if (conditional_expression1) {
ชุดคำสั่งที่ 1;} else if{ conditional_expression2) {
ชุดคำสั่งที่ 2 ;} else {
ชุดคำสั่งที่ 3;}
ชุดคำสั่งที่ 4;
ถ้าประโยคเงื่อนไข conditional_expression1 เป็นจริง ชุดคำสั่งที่ 1 จะทำงานแล้วข้ามมาทำชุดคำสั่งที่ 4 ถ้า conditional_expression1 เป็นเท็จ โปรแกรมจะตรวจสอบประโยคเงื่อนไขที่ 2 conditional_expression 2 ถ้าเป็นจริงชุดคำสั่งที่ 2 จะถูกประมวลผล แล้วข้ามไปทำชุดคำสั่งที่ 4 ถ้า conditional_expression 2 เป็นเท็จ ชุดคำสั่งที่ 3 จะทำงานแล้วต่อด้วยชุดคำสั่งที่ 4
กรณีที่มี if ..else ซ้อนกันหลาย ๆ ชั้น การใส่วงเล็บปีกกาจะช่วยให้ทราบว่า if กับ else ตัวไหนจับคู่กัน เช่น
If ( expression1) {
คำสั่งที่ 1;If (expression 2) คำสั่งที่ 2;
} else
คำสั่งที่ 3;
แสดงว่า else จับคู่กับ if ของบรรทัดแรก ถ้าไม่ใส่วงเล็บปีกกา else จะจับคู่กับ if ของบรรทัดที่ 2 โดยทั่วไป else จะจับคู่กับ if ที่อยู่ติดกันเสมอ
การใช้ if ในรูปแบบที่ 3 ซึ่งเป็นการใช้ if ซ้อน if เรียกแบบนี้ว่า nested if statement ในภาษา C++ สามารถใช้ if ซ้อน if ได้ไม่มีขีดจำกัด ในทางปฏิบัติการใช้ if ซ้อนกันหลายชั้น ทำให้เกิดการสับสนในการตรวจสอบการทำงานของโปรแกรม
โปรแกรม 2.1 จะทดลองนำการใช้ if ตรวจสอบเงื่อนไขการคำนวณหารากที่ 2 ของจำนวนเต็ม
[Soruce code: IFSQRT.cpp]
เมื่อให้โปรแกรม 2.1 ทำงาน เมื่อป้อนค่า -4 คำสั่งตรวจเงื่อนไข if พบว่า x มีค่าน้อยกว่าศูนย์ เงื่อนไขเป็นจริง คำสั่งในบรรทัดที่ 12 จะแสดงผลบนจอภาพว่า Don't input negative number แล้วข้ามมาทำบรรทัดที่ 16 แสดงผล Program terminated normally และจบการทำงาน
เมื่อให้โปรแกรมทำงานอีกครั้ง ทดลองป้อน +4 คำสั่ง if จะตรวจสอบพบว่า x มีค่ามากกว่าศูนย์ เงื่อนไขเป็นเท็จ โปรแกรมจะทำคำสั่งตามหลัง else (บรรทัดที่ 14) หาค่ารากที่สองของ x แล้วแสดงผลเป็น 2 ( )
ทดลองให้โปรแกรมทำงานอีกครั้ง แล้วป้อนค่า x ที่เป็นเลขทศนิยม เช่น 4.3 แล้วสังเกตผลลัพธ์ที่ได้ หรืออาจป้อนค่าจำนวนเต็ม เช่น 5 รากที่สองที่ได้จะแสดงผลเป็นจำนวนเต็มหรือไม่
ข้อสังเกต ถ้าประโยคคำสั่งที่ตามหลัง if หรือ else มีเพียงคำสั่งเดียว ไม่จำเป็นต้องใส่เครื่องหมายวงเล็บปีกกาปิดล้อมคำสั่ง แต่การใส่เครื่องหมายวงเล็บปีกกาจะทำให้ง่ายต่อการตรวจสอบ
If (x < 0 ) { cout << “don't input negative number \n”; } else { cout << “ Yes, positive number \n “; } | If (x < 0 ) cout << “don't input negative number \n”; else cout << “ Yes, positive number \n “; |
โปรแกรม 2.2 เป็นการหาค่าฟังก์ชัน เมื่อป้อนค่า x ใด ๆ โปรแกรมจะคำนวณหาค่า y พร้อมแสดงผลที่จอภาพ เมื่อป้อนค่า x =2 หรือ x = -2 โปรแกรมจะแจ้งเตือนว่าไม่สามารถหาค่า ได้ เพราะค่า x ดังกล่าว ทำให้เกิดกรณีการหารด้วยศูนย์
[Source code: IFFunc.cpp]
ผลการรันโปรแกรมจะเป็นดังรูป
นิพจน์เงื่อนไข (Conditional expression)
นิพจน์เงื่อนไขที่ตามหลัง if (หรือ while หรือ do while หรือ for) ต้องให้ค่าเป็น “ จริง ” หรือ “ เท็จ ” ข้อความในนิพจน์อาจจะอยู่ในรูปแสดงความสัมพันธ์กัน เช่น เท่ากับ มากกว่า น้อยกว่า หรืออยู่ในรูปของตรรกะ
เครื่องหมายที่ใช้แสดงความสัมพันธ์ (relation operator) เพื่อเปรียบเทียบระหว่างนิพจน์ 2 นิพจน์มีดังนี้
สัญลักษณ์
|
ความหมาย
|
ตัวอย่าง
|
==
| เท่ากับ | if ( x == 5) { … } |
!=
| ไม่เท่ากับ | if (x != 5) {…} |
<
| น้อยกว่า | if ( x < 5) { … } |
>
| มากกว่า | If (x > 5) { … } |
<=
| น้อยกว่าหรือเท่ากับ | if ( x <=5) { … } |
>=
| มากกว่าหรือเท่ากับ | if ( x >=5) { … } |
เครื่องหมายเชิงตรรกะ (logical operator) มีดังนี้
สัญลักษณ์
|
ความหมาย
|
ตัวอย่าง
|
&&
| และ (and) | A && B |
||
| หรือ (or) | A || B |
!
| ค่าความจริงที่ตรงข้าม (not) | !A |
A && B , A || B และ !A จะมีค่าเป็นจริงหรือเท็จ ให้ดูจากตารางค่าความจริงดังต่อไปนี้ F หมายถึง false
T หมายถึง true
T หมายถึง true
A
|
B
|
A && B
|
F
|
F
|
F
|
F
|
T
|
F
|
T
|
F
|
F
|
T
|
T
|
T
|
A
|
B
|
A || B
|
F
|
F
|
F
|
F
|
T
|
T
|
T
|
F
|
T
|
T
|
T
|
T
|
A
|
!A
|
F
|
T
|
T
|
F
|
ลำดับความสำคัญ (Precedence) ของเครื่องหมายแสดงความสัมพันธ์และเครื่องหมายตรรกะจะต่ำกว่าเครื่องหมายทางคณิตศาสตร์ แต่จะสูงกว่าเครื่องหมายกำหนดค่า ดังตารางต่อไปนี้
ตัวอย่างประโยคเงื่อนไข
ให้ a = 3, b=2 , c= -1 ประโยคเงื่อนไขของแต่ละ
ลำดับความสำคัญ
|
เครื่องหมาย
|
ลักษณะการกระทำเริ่มจาก
|
1
| ( ) | เริ่มจากวงเล็บในสุด |
2
| + - ++ -- cast ! (unary operator) | ขวาไปซ้าย |
3
| * / % | ซ้ายไปขวา |
4
| + - | ซ้ายไปขวา |
5
| < <= > >= | ซ้ายไปขวา |
6
| == != | ซ้ายไปขวา |
7
| && | ซ้ายไปขวา |
8
| || | ซ้ายไปขวา |
9
| = += -= *= /= %= | ขวาไปซ้าย |
ข้อต่อไปนี้ จะให้ค่าจริงหรือเท็จ
ก. a < b + c ประโยคนี้เป็นเท็จ เพราะ 3 < 1 ไม่เป็นจริง
ข. a + c >= b ประโยคนี้เป็นจริง เพราะ 2 เท่ากับ 2
ค. –c < c+10 ประโยคนี้เป็นจริง เพราะ -1 < 9
ง. a < 6 && a > 1 ประโยคนี้เป็นจริง เพราะ 3 < 6 และ 3 > 1
จ. a == b-c ประโยคนี้เป็นจริง เพราะ 3 เท่ากับ 2-(-1)
ฉ. a == b || b==c ประโยคนี้เป็นเท็จ เพราะ 3 == 2 หรือ 2 == -1
ข้อผิดพลาดที่พบบ่อยในการใช้ประโยคเงื่อนไข
ผู้เริ่มต้นเขียนโปแกรมภาษา C++ มักจะตกหลุมพรางต่อไปนี้เสมอ ประโยคเงื่อนไขต่อไปนี้ถูกหลักไวยากรณ์ของ C++ และเมื่อคอมไพล์ก็จะไม่แจ้งข้อความเตือนหรือผิดพลาด แต่ผลลัพธ์ของการทำงานของโปรแกรมไม่ตรงกับจุดประสงค์ที่ต้องการ
1. สับสนเครื่องหมาย = (การกำหนดค่า) กับเครื่องหมาย == ( เท่ากับ)
ถ้าต้องการตรวจสอบว่า i มีค่าเท่ากับ 10 หรือไม่ ประโยคที่ถูกคือ
If ( i == 10 ) cout << “i equals 10 \n”; // test exactly equality
แต่ถ้าเขียนแบบนี้
If ( i = 10 ) cout << “i equals 10 \n”; // test of the value assigned to i (zero or nonzero)
จะเป็นการตรวจสอบว่ามีการนำค่าคงที่ (ในที่นี้คือ 10) ใส่ไว้ในตัวแปร i หรือไม่ ประโยคนี้จะได้เงื่อนไขเป็นจริงเสมอ เพราะ i ไม่เท่ากับศูนย์
2. ประโยคทางคณิตศาสตร์ หมายถึง x มีค่ามากกว่าหรือเท่ากับ a แต่มีค่าน้อยกว่าหรือเท่ากับ b เมื่อเขียนในโปรแกรมมักจะเขียนเป็น
if ( a <= x <= b) cout << “ value of x = “ << x;
ถ้ากำหนดค่าให้ a = 2 b= 5 และ x = 6 ประโยคเงื่อนไขนี้จะได้ค่าที่ถูกต้องคือ เท็จ แต่ในการหาค่าจริงเท็จของประโยคนี้จะเริ่มจากซ้ายไปขวา เริ่มต้นด้วยเปรียบเทียบ a กับ x ( a <= x) จะได้ค่าเป็นจริงคือ 1 แล้วนำ 1 นี้ไปเปรียบเทียบกับ b ( 1 <= 5) ค่าที่ได้จะเป็นจริงคือ 1
3. เปรียบเทียบโดยใช้เครื่องหมาย == หรือ != กับตัวแปรที่มีชนิดข้อมูลเป็น float หรือ double ในทางทฤษฎีเป็นไปได้ที่จำนวนจริง 2 จำนวนมีค่าเท่ากัน แต่การเก็บเลขจำนวนจริงของคอมพิวเตอร์ ความเที่ยงตรง (precision) ของจำนวนเลข จะถูกจำกัดด้วยขนาดของหน่วยความจำที่ใช้เก็บ เลขจำนวนจริงจึงถูกปัดเศษ ทำให้เกิดความคลาดเคลื่อนไปจากค่าจริง ไม่ตรงกับที่เราต้องการ
การแปรียบเทียบควรตรวจสอบกับค่าความแม่นยำที่ยอมรับได้มากกว่า เช่นต้องการให้ค่าที่ได้ผิดพลาดได้ไม่เกิน 10 -6 ควรเปรียบเทียบดังนี้
If (fab(x-y) < 1.0e-6) cout << “ x = y”;
ไม่ควรใช้
If ( x == y) cout << “ x = y”;
ลองดูตัวอย่างต่อไปนี้
{ float x,y;
x = 0.123456780;
y=0.123456785;
if ( x == y )
cout << “ x equals to y”;else
cout << “ x not equals to y “:}
พบว่า จะได้เงื่อนไขเป็นจริง เนื่องจาก x และ y เป็นตัวแปรชนิด float ซึ่งขาดความเที่ยงตรงของทศนิยมตำแหน่งหลัง ๆ แต่ถ้ากำหนดให้ x และ y เป็นตัวแปรชนิด double พบว่าประโยคเงื่อนไขนี้จะให้ค่าเป็นเท็จ แต่ถ้านำประโยคนี้ไปคอมไพล์บนเครื่องที่กำหนดให้ตัวแปรชนิด float เป็นแบบ 32 บิต เงื่อนไขนี้จะให้ค่าจริงเช่นกัน
4. ประโยคเงื่อนไขจะมีค่าเป็นจริง (true) เมื่อค่าที่ได้ไม่เป็นศูนย์ นั่นหมายถึงจำนวนลบก็จะทำให้ได้ค่าจริงเช่นกัน การสร้างประโยคเงื่อนไขควรให้ค่าที่ได้ออกมาเป็นไปได้เพียงค่าเดียว คือควรตรวจสอบกรณีเป็นศูนย์จะดีกว่า เพราะจะลดความเสี่ยงของค่าต่าง ๆ ที่อาจเกิดขึ้นได้อย่างคาดไม่ถึง ค่าต่าง ๆ ต่อไปนี้ ทำให้ประโยคเงื่อนไขให้ค่าเป็นเท็จเสมอ
ชนิดข้อมูล | false value |
---|---|
char
|
'\0'
|
short
|
0
|
int
|
0
|
long
|
0L
|
float
|
0.0
|
double
|
0.0
|
pointer
|
null or 0
|
คำสั่งย่อสำหรับเงื่อนไข if … else
เราสามารถใช้เครื่องหมาย ? : เขียนประโยคคำสั่ง if… else ให้ดูกะทัดรัด โดยมีรูปแบบทั่วไปดังนี้
expression1 ? expression2 : expression3;
มีความหมายเหมือนกับ
If ( expression1)
expression2;else
expression3;
ตัวอย่าง เปรียบเทียบเลข 2 จำนวน แล้วพิมพ์เลขที่มีค่ามาก
if ( a > b) cout << a; else cout << b; | (a > b) ? cout << a : cout << b; |
ตัวอย่าง ถ้า x มากกว่าหรือเท่ากับ 0 ให้ z = x+2 ถ้าน้อยกว่า 0 ให้ z = x 2
if ( x >= 0) z = x+2; else z= x*x; | z = (x >= 0) ? x+2 :x*x; |
ตัวอย่าง ตัวแปรที่ชื่อ bit_val ต้องการพิมพ์ค่าบิตที่ 0 (บิตสุดท้ายทางขวามือ) ให้เป็นเลขฐานสองคือ 0 หรือ 1 ทำได้ดังนี้
if (( bit_val & 1)== 0) cout << ‘0'; else cout << ‘1'; | cout << (bit_val & 1) ? ‘0' : ‘1'; หรือ cout << (char)(‘0' + (bit_val & 1)); หมายเหตุ char เป็น casting operator |
การวนรอบโดยใช้คำสั่ง while หรือ do .. while เป็นการกระทำซ้ำชุดคำสั่งที่อยู่ในประโยค while ตราบเท่าที่ประโยคเงื่อนไขหลัง while มีค่าเป็นจริง (หรือไม่เป็นศูนย์) มีรูปแบบทั่วไปดังนี้
while (conditional_expression) {
Statements1;}
statements2;
do {
statements1;} while (conditional_expression);
statements2;
การทำงานของวงรอบ while จะตรวจสอบประโยคเงื่อนไข (conditional_expression) ก่อน ถ้าเป็นจริง ชุดคำสั่ง statements1 จะทำงาน ถ้าประโยคเงื่อนไขมีค่าเป็นเท็จ จะกระโดดข้ามมาทำ statements2 ทันที นั่นคือถ้าเริ่มต้นการทำงาน ประโยคเงื่อนไขเป็นเท็จ statements1 จะไม่มีการทำงานเลย
ส่วนการทำงานของ do .. while loop statements1 จะถูกประมวลผลในการวนรอบครั้งแรกเสมอ นั่นคือ statements1 ใน do .. while จะทำงานอย่างน้อยหนึ่งครั้ง
โปรแกรม 2.3 เป็นตัวอย่างการหาค่าเฉลี่ยของเลขชุดหนึ่ง โดยการป้อนตัวเลขผ่านแป้นพิมพ์ เมื่อป้อนครบเสร็จแล้วให้ป้อน
-99 โปรแกรมจะคำนวณหาค่าเฉลี่ยให้ทันที
-99 โปรแกรมจะคำนวณหาค่าเฉลี่ยให้ทันที
[Source code: FindAve.cpp]
ข้อสังเกต: ใน BCC5.5 ไม่สามารถใช้ Ctr + z ได้ ต้องพิมพ์ /0 เป็นข้อมูลสุดท้าย โปรแกรมจึงจะหาค่าเฉลี่ยให้
ภาษาคอมพิวเตอร์อื่น ๆ จะใช้คำสั่ง for ในการวนรอบเมื่อรู้จำนวนรอบที่จะวน แต่ for ในภาษา C++ มีความยืดหยุ่นมากกว่านั้น สามารถตรวจสอบประโยคเงื่อนไขได้ เหมือนกับคำสั่ง while ประโยค for ประกอบด้วย 3 ส่วน แต่ละส่วนคั่นด้วยเครื่องหมาย ; ประกอบด้วย ส่วนที่เป็นค่าเริ่มต้น (initial) ส่วนที่ตรวจสอบเงื่อนไข (conditional_expression) และส่วนที่ใช้ในการเพิ่มค่าหรือลดค่า (adjust)
For ( initial; conditional_expression ; adjust) {
Statements1;}
statements2;
โปรแกรม 2.4 เป็น ตัวอย่าง แสดงการหาผลรวมของ 1 + 2 + 3 + …+ 50
[Source code: Sum1to50.cpp]
โปรแกรม 2.5 เป็นตัวอย่าง แสดงการคนวณแฟคตอเรียลของเลขจำนวนเต็มบวก n โดยที่
n ! = n (n-1)(n-2)…1 เมื่อ n มากกว่าหรือเท่ากับ 0 และ 0 ! = 1
[Source code: Fac.cpp]
ทดลองให้โปรแกรมทำงาน แล้วทดสอบดูว่า เมื่อกำหนดให้ตัวแปร n เป็นชนิด int ค่า n มีค่าได้ไม่เกินเท่าใด ค่า n! จะยังคงไม่ผิดพลาด
ใน เทอร์โบ ซีพลัส พลัส พบว่า 8! = -25216 ค่าที่ถูกต้องคือ 40320 ค่านี้เกิน 32767 ซึ่งเป็นค่ามากที่สุดที่ตัวแปรชนิด int เก็บได้
ถ้าเปลี่ยนชนิดข้อมูลของตัวแปร n ให้เป็น unsigned long พบว่าหาค่าได้ถูกต้องถึง 32!
32! = 2147483648
โปรแกรม 2.6 เป็นตัวอย่าง การหา จำนวนเฉพาะ (Prime number) จำนวนเฉพาะคือ จำนวนเลขที่มากกว่า 1 และไม่มีเลขอื่นใดหารได้ลงตัวเลย ยกเว้นตัวมันเอง และ 1 จำนวนเฉพาะได้แก่ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, …
[Source code: Prime.cpp]
ตัวอย่างการหาจำนวนเฉพาะตั้ง 1 – 1000 จะเห็นว่าโปรแกรมนี้ข้าม 2 ซึ่งเป็นจำนวนเฉพาะด้วย
continue และ break
ในบางครั้งเราอาจต้องการให้การวนรอบที่เกิดจากการใช้คำสั่ง for หรือ while หรือ do .. while มีการเปลี่ยนแปลง เช่น สิ้นสุดลงก่อนที่จะครบตามเงื่อนไขที่กำหนด หรืองดเว้นการทำคำสั่งบางคำสั่งในระหว่างการวนรอบ
เมื่อการวนรอบของ for หรือ while หรือ do .. while พบกับคำสั่ง continue จะไม่มีการทำคำสั่งที่อยู่หลัง continue จะกระโดดข้ามไปวนรอบค่าต่อไปทันที ตัวอย่างเช่น การบวกเลขจำนวนคู่ตั้งแต่ 2 ถึง 10
[Source code: sum2to10.cpp]
คำสั่ง break ใช้เพื่อเป็นการออกจากการวนรอบกลางคัน โปรแกรมจะประมวลผลคำสั่งถัดไปที่ต่อจากการวนรอบ
การวนรอบแบบไม่รู้จบ (infinite loop)
บางครั้งเราต้องการบังคับโปรแกรมให้ทำงานวนรอบแบบไม่สิ้นสุด ตัวอย่างเช่น ในระบบควบคุม โปรแกรมอาจจะวนรอบเพื่อคอยรับค่าที่ได้จากหัววัด หรือระบบตรวจจับอื่น ๆ อย่างต่อเนื่องตลอดเวลาแล้วนำค่าเหล่านี้ไปประมวลผล ซึ่งโปรแกรมไม่สามารถจะหยุดทำงานได้ด้วยตัวมันเอง การหยุดการทำงานต้องอาศัยระบบปฏิบัติการที่เรียกว่า killing process ในระบบยูนิกซ์ ทำได้โดยกดปุ่ม Ctrl + c หรือ Ctrl + Q หรือใช้วิธี reset เครื่องคอมพิวเตอร์ เราสามารถสร้างการวนรอบแบบอนันต์ได้ดังนี้
while (1) {
statements;}
:
:
สำหรับ for loop
for ( ; ;) {
statements;}
:
:
สำหรับ do … while loop
do {
statements;} while (1);
:
:
การตรวจสอบเงื่อนไขโดยการใช้ if … else ซ้อนกันหลาย ๆ ชั้น อาจเลี่ยงมาใช้ switch จะทำให้การตรวจสอบดูง่าย โอกาสที่จะเกิดความผิดพลาดมีน้อยกว่า ตัวอย่างเช่น
if ( n == 1)statement1;else if ( n==2) statement2;else if ( n==3) statement3;else if ( n==4) statement4;else default_statements; | switch ( n) { case 1 : { statement1 ; break; }case 2 : { statement2; break; }case 3 : { statement3; break; }case 4 : { statement4; break; }default : default_statements; } |
บางครั้งเป็นการบังคับให้โปรแกรมทำงานตามอักขระที่เรากดแป้นพิมพ์ เช่น
cin << ch; if ( ch == ‘r') readdata();else if ( ch=='s') savedata();else if ( ch=='c') calculatedata();else if ( ch=='p') printdata(); | cin << ch; switch ( ch) { case ‘r' : { readdata(); break; }} |
รูปแบบของคำสั่ง switch
switch (expression) {
case constant1 : { statements1;}
break; }
case constant2 : { statements2;
break; }
case constant3 : { statements3;
break; }
:
:
default : { default_statements;
}
next_statements;
ตัวแปร expression ในวงเล็บของ switch จะต้องเป็นข้อมูลชนิด int หรือ char การใช้ข้อมูลแบบ string ดังต่อไปนี้ ไม่ถูกต้อง คอมไพเลอร์จะแสดงข้อความผิดพลาดขณะคอมไพล์
switch (stringvar) {
case “one” : { …. };}
case “two” : { … } ;
คำสั่ง switch จะทำการตรวจสอบตัวแปร expression ว่าจะไปทำคำสั่ง case ที่ลำดับใด ถ้าค่าใน expression เท่ากับ constant2 โปรแกรมจะกระโดมาทำคำสั่ง statement2 ที่อยู่ในบล็อกของ case constant2 เมื่อถึงคำสั่ง break โปรแกรมจะข้ามมาทำคำสั่ง next_statements
ถ้าค่าใน expression ไม่ตรงกับค่าคงที่ใด ๆ ที่ตามหลัง case เลย โปรแกรมจะทำคำสั่งที่อยู่ในบล็อก ของ default แล้วต่อด้วย next_statements
ข้อสังเกต
• คำสั่ง case จะสลับลำดับก่อนหลังอย่างไรก็ได้ เช่นเดียวกับ default จะนำไปเขียนตรงส่วนใดก็ได้ ในระหว่างคำสั่ง switch { … }
• คำสั่ง break จะเป็นการกำหนดให้โปรแกรมทำเฉพาะชุดคำสั่งที่อยู่ใน case นั้น ถ้าตัดคำสั่ง break ออก โปรแกรมจะประมวลผลไล่ตามลำดับลงมาเรื่อย ๆ รวมทั้งทำคำสั่งของ default ด้วย
• case แต่ละค่า สามารรถเขียนเรียงกันในบรรทัดเดียวกันได้ เช่น
case 1 : case 2 : statement ;
โปรแกรม 2.8 เป็น ตัวอย่างในการจัดกลุ่มการสอบย่อย ซึ่งมีคะแนนเต็ม 10 คะแนน นักศึกษาที่ได้คะแนน 8 – 10 คะแนน จัดอยู่ในกลุ่มเก่ง (Good) นักศึกษาที่ได้คะแนน 5-7 คะแนน จัดอยู่ในกลุ่มพอใช้ (Not bad) นักศึกษาที่ได้คะแนน 0 -4 คะแนน ต้องแก้ไขปรับปรุง (More practice)
มาถึงตอนนี้ เราได้เรียนรู้ การใช้ชนิดข้อมูลแบบต่าง ๆ ให้เหมาะสมกับงาน การใช้ตัวปฏิบัติการต่าง ๆ การควบคุมคำสั่งให้โปรแกรมวนรอบตามที่เราต้องการ ต่อไปนี้จะเป็นการนำความรู้เหล่านี้มาเขียนเป็นโปรแกรมสั้น ๆ เพื่อคำนวณและแก้ปัญหาทางคณิตศาสตร์ หรือทางวิทยาศาสตร์
โปรแกรม 2.9 และ 2.10 กำหนดตัวตั้ง (numerator) และตัวหาร (denominator) ทั้งคู่เป็นเลขจำนวนเต็มบวก โปรแกรมจะแสดงผลหารซึ่งเป็นจำนวนเต็ม (integer quotient) และเศษเหลือ (remainder) โดยกำหนดให้ วิธีที่ 1 ใช้เครื่องหมาย / และ % วิธีที่ 2 ห้ามใช้เครื่องหมาย / และ %
[Source code:Division.cpp]
โปรแกรม 2.10 ห้ามใช้เครื่องหมาย / และ % แต่จะใช้การวนรอบแก้ปัญหาแทน
[Source code: Divis2.cpp]
โปรแกรม 2.11 เป็นการหาตัวหารร่วมมาก ( ห.ร.ม.) (GCD, The Greatest Common Divisor) โดยใช้ Euclidean algorithm
อัลกอริธึมของ ยูคลิด สามารถเขียนเป็น flow chart ได้ดังนี้
ตัวอย่างเช่น จงหา ห.ร.ม.ของ 52, 128
• สลับที่ : 128, 52
• นำ 128 % 52 จะเหลือเศษ 24 จะได้ตัวเลขเก็บไว้เป็น 52, 24
• นำ 52 % 24 จะเหลือเศษ 4 จะได้ตัวเลขเป็น 24, 4
• นำ 4 % 2 จะเหลือเศษ 0 จะได้ตัวเลขเป็น 4,0
• ห.ร.ม. ของ 52, 128 คือ 4
ตัวอย่าง จงหา ห.ร.ม. ของ 532, 112
(532, 112 )--> (112,84) --> (84,28) --> (28,0) ห.ร.ม. ของ 532, 112 คือ 28
ตัวอย่าง จงหา ห.ร.ม. ของ 540, 432
(540, 432 ) --> (432,108) --> (108,0) ห.ร.ม. ของ 540, 432 คือ 108
[Source code:GCD.cpp]
โปรแกรม 2.12 ต้องการเรียงตัวเลขจำนวนเต็มให้ย้อนกลับทิศทางเดิม เช่น 1234 จะแสดงผล 4321
[Source code: Reverse.cpp]
ตัวอย่างการทำงาน
ข้อสังเกต 007 จะได้เป็น 7 และ 7500 จะได้เป็น 57
การสร้างเลขสุ่ม
การใช้โปรแกรมคอมพิวเตอร์จำลองสถานการณ์ (simulation) เช่น การทอดลูกเต๋า จับสลากออกรางวัล โดยให้คอมพิวเตอร์สร้างข้อมูลโดยสุ่มตัวเลขขึ้นมาเอง ตัวเลขที่คอมพิวเตอร์สุ่มขึ้นมานั้น ต้องไม่จำเพาะเจาะจง หรือคาดเดาตัวเลขที่จะสุ่มออกมาได้โดยวิธีใดวิธีหนึ่ง หรือมีรูปแบบที่แน่นอนตายตัว
ในภาษา C++ มีฟังก์ชัน rand() ใช้สร้างตัวเลขสุ่มที่มีค่าเป็นบวก ตั้งแต่ 0 ถึง RAND_MAX การใช้ฟังก์ชันนี้จะต้องใส่ header file ชื่อ stdlib.h ไว้ที่ต้นโปรแกรมด้วย
ทดลองสุ่มตัวเลขมา 10 ค่าโดยเขียนโปรแกรมดังนี้
[Source code: Random1.cpp]
ให้โปรแกรมทำงาน จะได้เลขสุ่ม ออกมา 10 ค่า โดยเขียนโปรแกรม ดังนี้
346
130
10982
1090
11656
7117
17595
6415
22948
31126
Maximum random number = 32767
จะเห็นเลขสุ่มที่ได้จะมีค่าไม่ซ้ำกันเลย และไม่สามารถเดาเลขสุ่มค่าถัดไปด้วยว่ามีค่าเท่าใด เพราะถูกสุ่มออกมาโดยไม่มีรูปแบบที่แน่นอน เมื่อให้โปรแกรมนี้ทำงานกับเครื่องคอมพิวเตอร์ต่างเครื่องกัน พบว่าอนุกรมเลขสุ่มอาจจะไม่เหมือน ดังที่เขียนไว้ในตัวอย่างนี้
เมื่อทดสอบให้โปรแกรมทำงานครั้งที่ 2 จะได้ผลลัพธ์ดังนี้
346
130
10982
1090
11656
7117
17595
6415
22948
31126
Maximum random number = 32767
และครั้งที่ 3
346
130
10982
1090
11656
7117
17595
6415
22948
31126
Maximum random number = 32767
โปรแกรมทำงานแต่ละครั้งจะสร้างเลขสุ่มตั้งแต่ 0 ถึง RAND_MAX ( ในที่นี้จะได้ค่า 32767) พบว่าเลขสุ่มที่ลำดับเดียวกันของทั้งสามครั้งจะเป็นเลขตัวเดียวกันหรือการทำงานแต่ละครั้งจะให้เลขสุ่มที่เป็นอนุกรมเดียวกัน ที่เป็นเช่นนี้ เพราะการทำงานของโปรแกรมแต่ละครั้งจะสร้างอนุกรมของตัวเลขจากจุดเริ่มต้น (seed) เดียวกัน ซึ่งจะกำหนดค่าโดยคอมพิวเตอร์โดยปริยาย และเป็นค่าเดียวกันทุกครั้งที่โปรแกรมนี้ทำงาน
คอมพิวเตอร์ไม่สามารถสร้างเลขสุ่มที่แท้จริง เพราะเมื่อให้ค่าอินพุตค่าเดียวกัน คอมพิวเตอร์จะให้ผลลัพธ์ออกมาเหมือนกันเสมอ แต่จำนวนที่ได้ทั้ง 10 ค่าจัดได้ว่าเป็นเลขสุ่ม เราเรียกเลขสุ่มที่ได้จากคอมพิวเตอร์นี้ว่าเป็นเลขสุ่มเทียม (psudo-random number)
ถ้ากำหนดจุดเริ่มต้น (seed) ที่ต่างกันไป จะได้อนุกรมของเลขสุ่มที่ต่างกัน โดยใช้ฟังก์ชัน sran( ) กำหนดจุดเริ่มต้นของเราเอง ไม่ต้องให้คอมพิวเตอร์กำหนดให้ จะได้ชุดเลขสุ่มที่ต่างกันไป ดังโปรแกรม 2.14 ต่อไปนี้
[Source code: Random2.cpp]
เมื่อกำหนดค่า seed =1, seed=123, seed = 500 และ seed =346 จะได้อนุกรมเลขสุ่มที่มีค่าต่างกันดังนี้
Input seed for random number : Seed = 1
346 130 10982 1090 11656 7117 17595 6415 22948 31126
-------------------------------------------------------------------
Input seed for random number : Seed = 123
9827 6588 24191 6712 22732 10409 17951 18683 8409 12981
-------------------------------------------------------------------------
Input seed for random number : Seed = 500
9312 23588 19347 13071 8345 3124 3206 30808 15588 15732
------------------------------------------------------------------------
Input seed for random number : Seed = 346
21517 24031 19326 29074 19611 14009 28003 15860 25345 1571
---------------------------------------------------------------------------
เมื่อพิจารณาอนุกรมเลขสุ่ม ที่ seed =1 พบว่าเป็นอนุกรมเดียวกันกับตัวเลขสุ่มที่ได้จากโปรแกรม random1.cpp แสดงว่าโปรแกรมได้กำหนดค่า seed = 1 เป็นค่าโดยปริยาย
เพื่อที่จะไม่ต้องกำหนดค่า seed ในแต่ละครั้งที่มีการสร้างเลขสุ่ม จะใช้ประโยชน์จากสัญญาณนาฬิกาของระบบคอมพิวเตอร์ เป็นผู้สร้างค่า seed ให้ ฟังก์ชัน time ( ) จะนำค่าเวลาของเครื่อง ณ ขณะนั้นส่งกลับเป็นเลขจำนวนเต็มบวก การใช้ฟังก์ชัน time () ต้องกำหนด header file ชื่อ time.h ไว้ที่ส่วนหัวของโปรแกรม
[Source code: Random3.cpp]
เมื่อให้โปรแกรมทำงานครั้งแรกจะได้ seed = 38620 จะได้เลขสุ่มออกมา 1 ชุด อีก 11 วินาทีต่อมา รันโปรแกรมอีกครั้งจะได้อนุกรมเลขสุ่มอีกชุดหนึ่ง ดังนี้
Seed = 38620
4974 27386 29523 668 25353 22414 13030 21087 9781 22631
Seed = 38631
8783 25014 17821 22931 10505 5253 29983 29177 27809 14280
โปรแกรม 2.16 เป็นเกมทายตัวเลข : คอมพิวเตอร์จะสุ่มตัวเลขจำนวนหนึ่งมีค่าระหว่าง 1 ถึง 100 จากนั้นให้ผู้เล่นทายว่าเลขนี้คือค่าเท่าใด เมื่อทายผิดในแต่ละครั้ง คอมพิวเตอร์จะบอกให้ว่าเลขที่ทายนั้นมากไปหรือน้อยไป โดยให้จำนวนครั้งที่ทายน้อยที่สุดเท่าที่จะเป็นไปได้
[Source code:GuessNum.cpp]
จากโปรแกรม 2.16 GuessNum.cpp จะเห็นว่า เราสามารถสร้างเลขสุ่มให้มีค่าอยู่ในช่วงที่ต้องการ เช่น จากโปรแกรมให้มีค่าระหว่าง 1 -100 นั่นคือ max =100 , min = 1 ช่วงของเลขสุ่มคือ range มีค่าเท่ากับ max – min + 1 นำไปหาเลขสุ่มได้จาก
number =
โปรแกรม 2.17 เกมไฮโลว์ มีลูกเต๋าอยู่ 3 ลูก เมื่อทอดลูกเต๋าแล้วนับจำนวนแต้มทั้งสามลูกซึ่งมีค่าระหว่าง 3 ถึง 18 ถ้ารวมแล้วน้อยกว่า 11 ถือว่าการทอดครั้งนี้ออก “ ต่ำ ” ถ้ามากกว่า 11 ถือว่าออก “ สูง ” ถ้ารวมกันได้ 11 พอดีจะถือว่าออก “ ไฮโลว์ “ (height – low) โปรแกรมนี้จะให้ผู้เล่นทายว่าลูกเต๋าทั้งสามลูกออกมา ต่ำ สูง หรือ
“ไฮโลว์ ” คอมพิวเตอร์จะสุ่มเลขสุ่ม ตั้งแต่ 1 ถึง 6 ออกมา 3 จำนวนแทนลูกเต๋าแต่ละลูก
“ไฮโลว์ ” คอมพิวเตอร์จะสุ่มเลขสุ่ม ตั้งแต่ 1 ถึง 6 ออกมา 3 จำนวนแทนลูกเต๋าแต่ละลูก
[Source code: HiLo.cpp]
ผลของการทำงานของโปรแกรมมีดังนี้
แบบฝึกหัดที่ 2
1. ต่อไปนี้ให้ค่าจริงหรือเท็จ
• 0
• 1
• x = 0
• -1
• x == 0
2. จงคาดคะเนผลลัพธ์จากโปรแกรมต่อไปนี้
#include <iostream>
//using namespace std;
int main () {
int x=1, y =1, z;return 0;
if ( z = (x-y))
cout << “z = “ << z;
}
3. จงคาดคะเนผลลัพธ์จากโปรแกรมต่อไปนี้
#include <iostream>
//using namespace std;
int main () {
int i=1;
int x;
while ( i < 100) {
cout << “ Input an integer :”;}
cin >> x;
return 0;
(เฉลย ต้องมีประโยค i++; มิฉะนั้นจะวนรอบไม่สิ้นสุด)
4. จงเขียนผลลัพธ์ของโปรแกรม
#include <iostream>
using namespace std;
int main () {
short int mynumber;
mynumber = 65535;
cout << “Now the number = “ << mynumber << endl;return 0;
mynumber ++;
cout << “Now the number = “ << mynumber << endl;
mynumber ++;
cout << “Now the number = “ << mynumber << endl;
}
[ เฉลย : ผลลัพธ์ จะได้เป็น
Now the number = 65535
Now the number = 0
Now the number = 1 ]
5. จงเขียนโปแกรมหาค่า e ยกกำลัง x
ให้ผู้ใช้ป้อนค่า x จากนั้นแสดงผล e x