บทที่6 การวนซ้า (Iteration) - e-Learning KKU

53
บทที6 การวนซ้า (Iteration) วัตถุประสงค์ 1) เข้าใจการวนซ ้าโดยใช้ค้าสั่งแบบต่างๆ 2) เลือกวิธีการวนซ้าที่เหมาะสมในการแก้ปัญหาตัวอย่าง 3) เขียนโปรแกรมที่มีการวนซ้าไดในการเขียนโปรแกรมภาษา C++ เราสามารถท้าให้เกิดการวนท้าซ้าส้าหรับค้าสั่งและบล็อคของค้าสั่งได้ อย่างเช่น ถ้าเราต้องการจะแสดงผลอักขระ a ออกทางหน้าจอ 50 ครัง เราไม่จ้าเป็นจะต้องสั่ง cout 50 ครัง แต่ เราจะใช้การควบคุมโปรแกรมด้วยการวนซ้า (iteration หรือ loop) แทน การวนซ้านันสามารถใช้เพื่อแสดงผล ออกทางหน้าจอซ้าๆ ใช้อ่านข้อมูลเข้ามาซ้าๆ ใช้จัดการกับแอเรย์ ใช้ค้านวณแบบที่ต้องท้าซ้าๆ หรืออื่นๆ ในท้านอง เดียวกันได้ ในภาษา C++ นัน เราใช้ค้าสั่ง while, do while, และค้าสั่ง for ในการวนซ้า เรื่องการวนซ้าเป็นเรื่องที่อาจจะเข้าใจยากสักหน่อยส้าหรับผู้เริ่มต้น ที่ส้าคัญคือนักศึกษาต้องเข้าใจการ เลือกท้าให้ดีเสียก่อน ไม่เช่นนันจะไม่เข้าใจการวนซ้า เพราะการวนซ้านันคือการสั่งโปรแกรมให้ท้าค้าสั่งชุดเดิมถ้ามี เงื่อนไขที่เหมาะสม 6.1 ค้าสั่ง while ค้าสั่ง while จะท้าค้าสั่งหรือบล็อคของค้าสั่งซ้าไปเรื่อยๆ ในขณะที่เงื่อนไข (condition) นันเป็นจริง และ จะหยุดท้าซ้าเมื่อเงื่อนไขนันเป็นเท็จ โดยรูปแบบการเขียนค้าสั่งแสดงในรูปที1 รูปที1 รูปแบบการใช้ค้าสั่ง while เราจะเห็นได้ว่ารูปแบบการเขียนนันเหมือนค้าสั่ง if มาก แต่ต่างกันตรงที่เมื่อค้าสั่ง if ตรวจสอบเงื่อนไข แล้วถ้าพบว่าเป็นจริงจะท้าค้าสั่งครังเดียวแล้วออกไปท้าค้าสั่งอื่นต่อไป แต่ค้าสั่ง while จะตรวจสอบเงื่อนไข เหมือนกัน แต่ถ้าเป็นจริงก็จะท้าค้าสั่งนันแล้วกลับมาตรวจสอบเงื่อนไขใหม่ ถ้ายังเป็นจริงอยู่ก็จะท้าค้าสั่งนันอีก ครัง และวนตรวจสอบและท้าค้าสั่งซ้าๆ จนกว่าเงื่อนไขของ while จะเป็นเท็จ ดังแสดงการท้างานในผังงานในรูปที2 ส่วนข้อแตกต่างการท้างานของ if และ while แสดงในรูปที3

Transcript of บทที่6 การวนซ้า (Iteration) - e-Learning KKU

บทท 6 การวนซ า (Iteration)

วตถประสงค

1) เขาใจการวนซ าโดยใชคาสงแบบตางๆ

2) เลอกวธการวนซ าทเหมาะสมในการแกปญหาตวอยาง

3) เขยนโปรแกรมทมการวนซ าได

ในการเขยนโปรแกรมภาษา C++ เราสามารถทาใหเกดการวนทาซ าสาหรบคาสงและบลอคของคาสงได อยางเชน ถาเราตองการจะแสดงผลอกขระ a ออกทางหนาจอ 50 คร ง เราไมจาเปนจะตองสง cout 50 คร ง แตเราจะใชการควบคมโปรแกรมดวยการวนซ า (iteration หรอ loop) แทน การวนซ าน นสามารถใชเพอแสดงผลออกทางหนาจอซ าๆ ใชอานขอมลเขามาซ าๆ ใชจดการกบแอเรย ใชคานวณแบบทตองทาซ าๆ หรออนๆ ในทานองเดยวกนได ในภาษา C++ น น เราใชคาสง while, do while, และคาสง for ในการวนซ า

เรองการวนซ าเปนเรองทอาจจะเขาใจยากสกหนอยสาหรบผเรมตน ทสาคญคอนกศกษาตองเขาใจการเลอกทาใหดเสยกอน ไมเชนน นจะไมเขาใจการวนซ า เพราะการวนซ าน นคอการสงโปรแกรมใหทาคาสงชดเดมถามเงอนไขทเหมาะสม

6.1 คาสง while

คาสง while จะทาคาสงหรอบลอคของคาสงซ าไปเรอยๆ ในขณะทเงอนไข (condition) น นเปนจรง และจะหยดทาซ าเมอเงอนไขน นเปนเทจ โดยรปแบบการเขยนคาสงแสดงในรปท 1

รปท 1 รปแบบการใชคาสง while

เราจะเหนไดวารปแบบการเขยนน นเหมอนคาสง if มาก แตตางกนตรงทเมอคาสง if ตรวจสอบเงอนไข แลวถาพบวาเปนจรงจะทาคาสงคร งเดยวแลวออกไปทาคาสงอนตอไป แตคาสง while จะตรวจสอบเงอนไขเหมอนกน แตถาเปนจรงกจะทาคาสงน นแลวกลบมาตรวจสอบเงอนไขใหม ถายงเปนจรงอยกจะทาคาสงน นอกคร ง และวนตรวจสอบและทาคาสงซ าๆ จนกวาเงอนไขของ while จะเปนเทจ ดงแสดงการทางานในผงงานในรปท 2 สวนขอแตกตางการทางานของ if และ while แสดงในรปท 3

รปท 2 ผงงานของคาสง while

รปท 3 เปรยบเทยบผงงานของคาสง if และ while

ในการวนซ าน น เนองจากในทสดแลวเงอนไขจะตองเปนเทจโปรแกรมถงจะหยดการวนซ าได เพราะฉะน นเราจะตองมการปรบคาของตวแปร (update) ทเปนเงอนไขในการวนซ าในแตละรอบเสมอ ไมทางใดกทางหนง เชน การเพมหรอลดคาในแตละรอบ หรอการเปลยนคาโดยการคานวณหรอการรบเขาผานทางแปนพมพ

การวนซ าตามจานวนคร งทกาหนดให

เราสามารถเขยนโปรแกรมเพอวนซ าเปนจานวนคร งทแนนอนได โดยอาศยตวนบรอบ (counter) เพอเปรยบเทยบกบคาจานวนรอบทเราตองการวาเราทาซ าครบตามจานวนรอบน นหรอยง

ตวอยางท 1

โจทย : จงเขยนโปรแกรมภาษา C++ เพอแสดงขอความ hello ออกทางหนาจอ 10 คร ง

1) เอาตพต คอขอความ hello 10 คร ง 2) อนพต ไมม 3) โจทยไมไดกาหนดอะไรเพมเตม 4) ไมมขอมลอะไรเพมเตม

เนองจากตวอยางน เปนตวอยางแรกของการวนซ า เราจะขออธบายผงงานในรปท 4 กอน โจทยขอน เปนการวนซ าตามจานวนคร งทกาหนดให โปรแกรมจะเรมตนดวยการต งคาตวแปร i ใหเทากบ 0 เราเรยกตวแปร i วาตวนบ (counter) เปนตวนบจานวนรอบวาเราวนทาไปกรอบแลว เพราะฉะน นในแตละรอบ i จะเพมคาข นไปเรอยๆ ทละหนง โจทยกาหนดใหทาตามจานวนคร ง ในทน คอ 10 คร ง เพราะฉะน นเราจงตองใชตวแปร i เปนเงอนไขในการวนซ า คอเราจะตรวจสอบทกๆ รอบวาเราไดแสดงขอความ hello ไปท งหมด 10 คร งหรอยง ถาเรายงแสดงขอความไดนอยกวา 10 รอบ เรากทาตอไป แตถาเราทาครบ 10 คร งแลว เรากจะหยดทาและออกจากลป (loop) ไปทาคาสงตอไป

รปท 4 ผงงานการวนซ า 10 รอบ

จากผงงาน เราสามารถเขยนโคดไดดงรปท 5 เราจะเหนไดวาเราเขยนโคดโดยมการประกาศและใหคา i กอนจะเขาตรวจสอบเงอนไข จากน นเราเขยน while( i < 10) เพอแทนลปของการตรวจสอบเงอนไขวาจะทาคาสง cout (เขยนคาวา Hello ออกทางหนาจอ) และการเพมคา i หรอไม

รปท 5 ความสมพนธของผงงานและโคดของการวนซ า 10 รอบ

ทน ถาเราตองการแสดงขอความ hello ออกทางหนาจอ 100 คร ง เราตองเปลยนโคดอยางไรบาง จากตวอยางท 1 เราทราบวาถาตองการวนซ า 10 รอบ เราเอาคา 10 ไปเปรยบเทยบกบ i (counter) เพอทจะนบวาเราทาครบ 10 รอบหรอยง เพราะฉะน นถาเราตองการแสดง hello ออกทางหนาจอ 100 รอบ เราจงเปลยนตวเปรยบเทยบจากคา 10 เปนคา 100 ดงโคดตอไปน

โคด:

int main(){

int i = 0;

while(i < 100){

cout << "Hello " << endl;

i++;

}

}

แลวถาโจทยตองการใหรบจานวนรอบทตองวนซ าผานทางแปนพมพ เราตองเปลยนโคดอยางไรบาง ในทานองเดยวกน แทนทจะเทยบ i กบ 100 เราจะใหเปรยบเทยบ i กบ n ซงเปนจานวนคร งทเรารบมาจากแปนพมพ เราเขยนโคดไดดงน

โคด:

int main(){

int i = 0, n;

cout << "Enter n: ";

cin >> n;

while(i < n){

cout << "Hello " << endl;

i++;

}

}

ตวอยางท 2

โจทย : จงเขยนโปรแกรมภาษา C++ เพอแสดงเลขจานวนเตมจาก 1-10 ออกทางหนาจอโดยใชการวนซ า

1) เอาตพต คอเลข 1-10 เรยงกน 2) อนพต ไมม 3) โจทยไมไดกาหนดอะไรเพมเตม 4) ไมมขอมลอะไรเพมเตม

โจทยขอน เราใชการวนซ าในการแสดงเลข 1-10 เราสามารถแสดง i (counter) ออกไปทางหนาจอไดเลย นนคอในรอบท 1 เราแสดง 1 รอบท 2 เราแสดง 2 ไปเรอยๆ จนถงรอบท 10 แตเราจะตองเปลยนตาแหนงการอปเดตคา i ไมเชนน นเราจะไดผลลพธเปน 0-9 แทน เราเขยนโคดไดดงน

โคด:

int main(){

int i = 0;

while(i < 10){

i++; // เปลยนมาอปเดตกอนแสดงผล

cout << i << endl;

}

}

จรงๆ แลวในโจทยขอน และในโจทยทวไป เราสามารถเขยนโคดไดหลายแบบ เนองจากการเปรยบเทยบคา i เปนตวควบคมการแสดงผลและการวนซ า เราสามารถคงลาดบการเปลยนแปลงคา i ไวทเดมได แตเราตองปรบเปลยนการเปรยบเทยบคา i และ/หรอ เปลยนคาต งตนของ i และ/หรอ เปลยนการแสดงคา i เชน เราสามารถเขยนโปรแกรมไดดงน

โคด:

int main(){

int i = 1;

while(i <= 10){

cout << i << endl;

i++;

}

}

หรอ

โคด:

int main(){

int i = 0;

while(i < 10){

cout << i+1 << endl;

i++;

}

}

ในทานองเดยวกบการวนซ าเพอแสดงขอความ hello ถาเราตองการแสดงเลข 1-100 หรอ 1-n เรากสามารถเปลยนโคดตรงการเปรยบเทยบ i เพอแสดงคาดงกลาวได เราจะแสดงตวอยางของโคดทแสดงจานวนเตมจาก 1-n ขางลางน

โคด:

int main(){

int i = 1, n;

cout << "Enter n: ";

cin >> n;

while(i <= n){

cout << i << endl;

i++;

}

}

ตวอยางท 3

โจทย : จงเขยนโปรแกรมภาษา C++ เพอแสดงผลรวมของเลขจานวนเตมจาก 1-n ออกทางหนาจอโดยใชการวนซ า

1) เอาตพต คอผลรวมของเลขจานวนเตมจาก 1-n 2) อนพต คอจานวนเตม n 3) โจทยไมไดกาหนดอะไรเพมเตม 4) ไมมขอมลอะไรเพมเตม

โจทยขอน จะคลายๆ กบตวอยางท 2 แตตางกนตรงทแทนทจะแสดงจานวนออกไปเลย แตเราเอาจานวนน นมารวมกบจานวนกอนหนาน ดงน น นอกจากทเราตองมการนบรอบดวยตวนบ (counter) แลว เราตองมตวแปรอกตวหนงเพอทจะมาเกบคาผลรวมของแตละรอบไว นนคอผลรวมของรอบปจจบนจะเทากนผลรวมของรอบทแลว (ทถกเกบไวในตวแปรหนง) บวกกบตวนบ (counter) ของรอบน ดงแสดงตวอยางในการบวกจานวนเตมต งแต 1-5 ในตารางท 1

ตารางท 1 คาของตวแปรในแตละรอบของการวนซ าเพอหาผลรวม

รอบท ผลรวมรอบทแลว (sum กอนบรรทดท 7)

ตวนบทจะบวกเขาไป (i)

ผลรวมใหมของรอบน (sum หลงบรรทดท 7)

เรมตน 0 1 1 0 1 1

2 1 2 3

3 3 3 6 4 6 4 10

5 10 5 15

เราสามารถเขยนโคดไดดงน โดยเรากาหนดตวแปรเพมคอ sum เพอเกบคาผลรวมในแตละรอบ แลวใหคาเรมตนเปน 0 เพราะ 0 บวกคาใดกจะไดคาน น ทาใหเราไดคาทถกตองในการบวกในรอบแรกของลป

โคด:

1

2

3

4

5

6

7

8

9

10

int main(){

int i = 1, n, sum = 0;

cout << "Enter n: ";

cin >> n;

while(i <= n){

sum = sum + i; // or sum += i;

i++;

}

}

เราจะเหนไดวา เราเกบคาผลรวมไวในตวแปร sum ในรอบปจจบนตวแปร sum จะเกบคาผลรวมของรอบทแลวไวกอน (กอนบรรทดท 7) เมอเราบวก i เขาไปแลว เรากเกบผลรวมใหมของรอบน ไวในตวแปร sum เหมอนเดม เพอทจะเอาไปใชในรอบถดไปได

การวนซ าตามคาปจจบนของตวแปร

ในหวขอทแลวเราวนซ าเปนจานวนรอบทแนนอน แตทจรงแลวเรายงสามารถทาการวนซ าจนกวาเราจะไดคาทตองการไดโดยไมจากดจานวนรอบ เราตองทาการเปรยบเทยบคาทเราสนใจกบคาทเราตองการ ดงตวอยางตอไปน

ตวอยางท 4 การหาผลรวมของสวนกลบ (reciprocal)

โจทย : จงเขยนโปรแกรมภาษา C++ เพอรบเลขจานวนเตม bound จากแปนพมพ จากน นใหหาผลรวมของสวนกลบ i ตวทมคาไมเกน bound

1) เอาตพต คอผลรวมเลขสวนกลบ i ตวทมคาไมเกน bound 2) อนพต คอจานวนเตม bound 3) โจทยไมไดกาหนดอะไรเพมเตม 4) สวนกลบ (reciprocal) คอเลขทคณกบสวนของมนแลวได 1 อยางเชน 1/3 คณ 3 ได 1 นนคอ 1/3 เปน

สวนกลบของ 3

ในโจทยขอน เราจะตองบวก 1/i ไปเรอยๆ ต งแต i เทากบ 1 คอ 1 + ½ + 1/3 + ¼ + … ไปเรอยๆ จนกวาคาผลรวมจะเกน bound เพราะฉะน น เรารไดวาเงอนไขในการวนซ าคอ ผลรวมปจจบนนอยกวา bound เราถงทาการวนซ าตออก

โคด:

int main(){

float i = 1;

float bound, sum = 0;

cout << "Enter bound: ";

cin >> bound;

while(sum < bound){

sum += 1/i;

cout << "The sum of the first " << i << " reciprocals

is "

<< sum << endl;

i++;

}

}

การวนซ ารบคาจากแปนพมพ

นอกจากการวนซ าสองแบบขางตน เราสามารถวนซ าเพอรบคาผานทางแปนพมพได นนคอการวางคาสง cin ไวในลป ซงเงอนไขในการวนซ าอาจจะเกยวกบคาทรบเขามาผานทางแปนพมพหรอไมเกยวกได

ตวอยางท 5

โจทย : จงเขยนโปรแกรมภาษา C++ เพอรบเลขจานวนจรง x จากแปนพมพ จากน นแสดงคารากทสองของ x ออกทางหนาจอ แลววนรบคา x และแสดงคารากทสองของ x ซ าจนกวาผใชจะใส 0 ผานทางแปนพมพ

1) เอาตพต คอคารากทสองของ x 2) อนพต คอจานวนจรง x โดยวนซ าเพอรบคาเขามา จนกวา x จะเปน 0 3) โจทยไมไดกาหนดอะไรเพมเตม 4) เรารวาการหารากทสองของ x เราสามารถใชฟงกชน sqrt() ในไลบราร cmath ได

ความทาทายของโจทยขอน อยทการวนรบคาเขามา เรารวาคาสงในการรบคาคอ cin เพราะฉะน น cin จงตองอยในลปและจะตองอยกอนการตรวจสอบวาคา x มากกวา 0 หรอไม

โคด:

#include <cmath>

int main(){

double x;

cout << "Enter a positive number: ";

cin >> x;

while(x > 0){

cout << "Square root (" << x <<

") = " << sqrt(x) << endl;

cout << "Enter another positive "

<< "number (or 0 to quit): ";

cin >> x;

}

return 0;

}

จรงๆ แลวในโคดเราจะตองม #include <iostream> ดวย แตเราอนมานเอาวามนมในทกไฟลอยแลว จงเพมแค #include <cmath> เขาไปเพอทจะใชฟงกชน sqrt()

การวนซ าโดยใชคาทมาจากในอดตมากกวาหนงรอบ

ในบางกรณ เราตองการใชคาทมาจากการวนซ าในอดตมากกวาหนงรอบข นไป ในกรณน เราตองเพมตวแปรข นมาเพอเกบคาในอดตในแตละรอบ ตวอยางเชน การหาเลขไฟโบนาชช (Fibonacci number) ซงถกนยามคอ

𝒇𝒏 = 𝒇𝒏−𝟐+𝒇𝒏−𝟏

โดยกาหนดให f0 = 0 และ f1 = 1 ซงหมายความวา คาของเลขไฟโบนาชชตวท n คอผลรวมของคาตวท n-1 และคาตวท n-2 ดงแสดงในรปท 6

รปท 6 เลขไฟโบนาชช

ในการหาเลขไฟโบนาชชน เราสามารถใชการวนซ าในการหาได โดยการหา fn ในการวนรอบท n ซงจะตองใชคาในรอบท n-1 (รอบทแลว) และคาในรอบท n-2 (สองรอบทแลว) เราจงตองมการใชตวแปรสองตวในการเกบคาของรอบทแลวและคาในสองรอบทแลวดวย โดยมโคดในการคานวณดงน

โคด:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

#include <cmath>

int main(){

int n;

cout << “Enter a positive integer: ”;

cin >> n;

cout << “First ” << n << “ Fib. numbers: ”;

if(n >= 1) cout << “0”;

if(n >= 2) cout << “, 1”;

int a = 0, b = 1;

int i = 3;

while(i <= n){

int f = a + b;

cout << “, ” << f;

a = b;

b = f;

i++;

}

return 0;

}

ในโคดน โปรแกรมรบคาจานวนเตมบวก n ผานทางแปนพมพ จากน นจะคานวณเลขไฟโบนาชช n ตวแรก โดยเรมจาก f0 ดงน นถา n มคาเปน 1 (นนคอแสดงแค f0) โปรแกรมกจะพมพ 0 ออกทางหนาจอ (จากคาสงในบรรทดท 9) แลวจบโปรแกรม ถา n เปน 2 (นนคอแสดงแค f0 และ f1) โปรแกรมกจะพมพ 0 (จากคาสงใน

บรรทดท 9), 1 (จากคาสงในบรรทดท 10) แลวออกจากโปรแกรม เราไมสามารถเรมวนซ าเมอ n เปน 1 หรอ 2 ได เพราะเราไมสามารถมคาในอดตอยางนอย 2 รอบได จงตองมเงอนไขมากาหนดคาใหแทน

แตถา n มคามากกวา 2 เราสามารถเรมวนซ าได โดยกาหนดให i เรมท 3 (คานวณ f2) และกาหนดใหตวแปร b เกบคาของ f ในรอบทแลว (fn-1) โดยเรมจากมคาเทากบ 1 (คา f1) และใหตวแปร a เกบคาของ f ในสองรอบทแลว (fn-2) โดยเรมจากมคาเทากบ 0 (คา f0) เมอคานวณคา fn ในบรรทดท 15 แลว เรากจะตองมการปรบคา (update) เพอการคานวณในรอบถดไป น นคอ คา a (fn-2) ในรอบถดไปจะเปนคา fn-1 ในรอบน (a = b ในบรรทดท 17) สวนคา b (fn-1) ในรอบถดไปจะเปนคา fn ในรอบน (b = f ในบรรทดท 18) สดทายใหเพมคา i ข นเพอเปนการนบรอบ ถาทาครบรอบแลวกจบโปรแกม แตถายงทาไมครบ n ตวกใหวนซ าหาคา f โดยเรมจากบรรทดท 15 อกคร งหนง เราสามารถไลคาของ i, a, b และ f ในแตละรอบไดดงน

ตารางท 2 คาของตวแปรในแตละรอบของการหาเลขไฟโบนาชช ทบรรทดท 15 ของโปรแกรม

i f (fn) a (fn-2) b (fn-1) 3 1 0 1

4 2 1 1

5 3 1 2 6 5 2 3

7 8 3 5

8 13 5 8 9 21 8 13

10 34 13 21

การหยดการทางานของลป (Terminating a loop)

เราสามารถใสเงอนไขอกแบบเขาไปในคาสง while นนคอ true เมอเราใส true เปนเงอนไขของ while ลปจะทาการวนซ าไปเรอยๆ ไมมทส นสด (infinite loop) เพราะเงอนไขเปนจรงตลอดเวลา ดงน นหากเราตองการหยดการวนซ า เราจงตองใสคาสงตอไปน เพอจะหยดการวนซ าและใหไปทาคาสงอนตอไป

1) break; คาสงน จะหยดเฉพาะลปทคาสงน อยเทาน น จากน นโปรแกรมจะทาคาสงถดไปทตอจากลป 2) exit(0); คาสงน จะทาใหลปหยดการทางาน และท งฟงกชนจะจบการทางานเลย จะไมทาคาสงทเหลอใน

ฟงกชนอก

3) return; คาสงน จะทาใหลปหยดการทางาน และท งฟงกชนจะจบการทางานเลย จะไมทาคาสงทเหลอในฟงกชนอก

การใชคาสงเหลาน โดยทวไปแลวเราตองมเงอนไขเพมเตมในลป โดยเมอเงอนไขทวาเปนจรง โปรแกรมกจะทาการหยดลป อยางเชน การกาหนดคาสง

while(true)

if(i > n) break;

หมายความวาใหวนลปไปเรอยๆ ไมมทส นสด แตเมอ i มากกวา n แลวใหทาการหยดลป

ตวอยางท 6

โจทย : จงเขยนโปรแกรมภาษา C++ เพอแสดงผลรวมของเลขจานวนเตมจาก 1-n ออกทางหนาจอโดยใชการวนซ าแบบไมมทส นสด

1) เอาตพต คอผลรวมของเลขจานวนเตมจาก 1-n 2) อนพต คอจานวนเตม n 3) โจทยกาหนดใหใชการวนซ าแบบ infinite loop 4) ไมมขอมลอะไรเพมเตม

เราเคยทาโจทยขอน ไปแลวในตวอยางท 3 โดยมเงอนไขการวนซ าคอเมอ i <= n ใหทาตอ แตโจทยน กาหนดใหวนซ าแบบไมมทส นสด ทาใหเราตองกาหนดเงอนไขใหลปหยด นนคอเมอ i > n เราตองทาการหยดลป

โคด:

1

2

3

4

5

6

7

8

9

10

int main(){

int i = 1, n, sum = 0;

cout << "Enter n: ";

cin >> n;

while(true){

sum += i;

i++;

if(i > n) break;

}

11

12

13

14

15

cout << "The sum of the first " << n << " integers is "

<< sum << endl;

return 0;

}

ถาเราใสขอมลผานทางแปนพมพเปน 5 เรากจะไดเอาตพตเปนดงน

ผลการทางาน:

Enter n: 5

The sum of the first 5 integers is 15

ถาหากเราเปลยนคาสงจาก break เปน exit(0) หรอ return จะเกดอะไรข น เหมอนทกลาวไปขางตนวาคาสง exit(0) และ return จะทาใหท งฟงกชนจบการทางานหลงจากบรรทดท 9 ดงน นโปรแกรมจะไมมการ cout ผลการบวกออก ผลรนจงจะเหลอแคดงน

ผลการทางาน:

Enter n: 5

หมายเหต ทจรงแลวโปรแกรมจะมการหาผลรวมไดถกตอง แตมนจะไมแสดงผลออกทางหนาจอ เนองจากตองจบการทางานของฟงกชนในบรรทดท 9 กอนทจะมการทาคาสง cout ในบรรทดท 11

6.2 คาสง do while

คาสง do while เปนอกคาสงสาหรบการวนซ า แตตางจากคาสง while ตรงทคาสง do while จะทาคาสงในลปกอนรอบหนง แลวจงคอยตรวจสอบเงอนไขวาจะทาการวนลปอกคร งหรอไม แตคาสง while จะ

ตรวจสอบเงอนไขกอนทจะทาคาสงในรอบแรก ถาเงอนไขเปนจรงจงจะทาคาสงในลป ผงงานแสดงความแตกตางน แสดงในรปท 7

รปท 7 เปรยบเทยบผงงานการทางานของ while และ do while

รปแบบการเขยนคาสง do while แสดงในรปท 8 คาสงเขยนวา do คอทาคาสงทอยในลปกอน แลวจงตรวจสอบ while ถาเงอนไขน นเปนจรงกใหวนลปอก เราสงเกตวาหลงสวนของคาสง do while น นมเครองหมายเซมโคลอน (;) ปดอย ตางจากคาสง while ธรรมดาทจะไมมเครองหมายเซมโคลอนปดอย

รปท 8 รปแบบคาสง do while

โดยทวไปแลวเราสามารถดดแปลงโคดทใชคาสง while มาเปนโคดทใชคาสง do while ได แตในบางกรณกจะตองมการปรบเปลยนตาแหนงของคาสงตางๆ เพอความถกตอง ท งน เพราะในคาสง while โปรแกรมจะทาการตรวจสอบเงอนไขกอน แตในคาสง do while โปรแกรมจะทาคาสงในลปกอนแลวจงจะตรวจสอบเงอนไขสาหรบการทาในรอบตอไป ดงน นการเรยงคาสงในโปรแกรมอาจจะมความแตกตางกน

ตวอยางท 7

โจทย : จงเขยนโปรแกรมภาษา C++ เพอแสดงผลรวมของเลขจานวนเตมจาก 1-n ออกทางหนาจอโดยใชการวนซ าดวยคาสง do while

1) เอาตพต คอผลรวมของเลขจานวนเตมจาก 1-n 2) อนพต คอจานวนเตม n 3) โจทยกาหนดใหใชการวนซ าดวยคาสง do while

4) ไมมขอมลอะไรเพมเตม

เราเคยทาโจทยขอน ไปแลวในตวอยางท 3 และ ตวอยางท 6 โดยใชคาสง while เราจะเหนไดวา ในตวอยางน โคดน นเหมอนกบโคดในตวอยางท 3 ทใชคาสง while

โคด:

int main(){

int i = 0, n, sum = 0;

cout << "Enter n: ";

cin >> n;

do{

i++;

sum += i;

}while(i < n)

cout << "The sum of the first " << n << " integers is "

<< sum << endl;

return 0;

}

ตวอยางท 8 การหาคาแฟกทอเรยล n ตวแรก

โจทย : จงเขยนโปรแกรมภาษา C++ เพอแสดงเลขแฟกทอเรยลจาก 1 ถง n โดยโปรแกรมจะทาการรบคา n เปนจานวนเตมผานทางแปนพมพ ใหทาสองแบบโดยใชคาสง do while และคาสง while

1) เอาตพต คอเลขแฟกทอเรยลจาก 1! ถง n! 2) อนพต คอจานวนเตม n 3) โจทยกาหนดใหใชการวนซ าดวยคาสง do while และคาสง while 4) คาแฟกทอเรยล คอผลคณของจานวนนบต งแต n ลงไปถง 1 (หรอ 1 ถง n) เชน 5! คอ 5*4*3*2*1 ซงเรา

ไดอธบายไปในตวอยางในบทอลกอรทมและผงงานแลว

การเขยนโปรแกรมวนซ าเพอหาคาแฟกทอเรยลกจะคลายกบการวนซ าเพอหาคาผลรวมในตวอยางทผานมา แตจะตางกนตรงทแทนทจะเกบคาผลบวก เรากเกบคาผลคณแทน และคาเรมตนของตวเกบผลคณ (fac) จะเปน 1 เพราะ 1 คณคาใดจะไดคาน นเสมอ ซงจะทาใหผลคณในการวนรอบแรกน นถกตอง คาของ fac และ i ในแตละรอบแสดงในตารางท 3

ตารางท 3 คาของตวแปรในแตละรอบของการวนซ าเพอหาผลคณ

รอบท ผลคณรอบทแลว (fac กอนบรรทดท 10)

ตวนบทจะคณเขาไป (i)

ผลคณใหมของรอบน (fac หลงบรรทดท 10)

เรมตน 1 1 1 1 2 2

2 2 3 6 3 6 4 24

4 24 5 120

เราสามารถเขยนโคดโดยใชคาสง do while และ while ไดดงน

โคด: ใชคาสง do while

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

int main(){

int n;

cout << "Enter a positive integer: ";

cin >> n;

cout << "Factorial numbers: 1 ";

long fac = 1, i = 1;

do{

i++;

fac *= i;

cout << fac << " ";

} while(i < n){

cout << endl;

return 0;

}

โคด: ใชคาสง while

int main(){

int n;

cout << "Enter a positive integer: ";

cin >> n;

cout << "Factorial numbers: 1 ";

long fac = 1, i = 1;

while(i < n){

i++;

fac *= i;

cout << fac << " ";

}

cout << endl;

return 0;

}

ในตวอยางน โคดโดยใชคาสง while และ do while มการใชคาสงตางๆ คลายกนมาก แตใหระลกไววาไมใชทกกรณทจะเปนเชนน เราจงตองตรวจสอบผลรนของโคดเสมอ

ตวอยางท 9 การหาคาแฟกทอเรยล n ตวแรกทไมเกนคาทกาหนดให

โจทย :จงเขยนโปรแกรมภาษา C++ เพอแสดงเลขแฟกทอเรยลจาก 1 ถงคาแฟกทอเรยลทมคาไมเกน bound โดยโปรแกรมจะทาการรบคา bound เปนจานวนเตมผานทางแปนพมพ ใหทาสองแบบโดยใชคาสง do while และคาสง while

1) เอาตพต คอเลขแฟกทอเรยลจาก 1 ถงคาแฟกทอเรยลทมคาไมเกน bound 2) อนพต คอจานวนเตม bound 3) โจทยกาหนดใหใชการวนซ าดวยคาสง do while และคาสง while 4) ไมมขอมลอะไรเพมเตม

ตวอยางน เหมอนตวอยางทแลว แตตางกนตรงทเราไมสามารถวนซ าเปนจานวนรอบทแนนอนได แตเราตองตรวจสอบวาคาแฟกทอเรยลในปจจบนน นเกนคา bound ทรบเขามาจากแปนพมพหรอไม

โคด: ใชคาสง do while

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

int main(){

int bound;

cout << "Enter a positive integer: ";

cin >> bound;

cout << "Factorial numbers: ";

long fac = 1, i = 1;

do{

cout << fac << " ";

i++;

fac *= i;

} while(fac <= bound);

cout << endl;

return 0;

}

โคด: ใชคาสง while

1

2

3

4

5

6

7

8

9

10

11

12

int main(){

int bound;

cout << "Enter a positive integer: ";

cin >> bound;

cout << "Factorial numbers: ";

long fac = 1, i = 1;

while(fac <= bound){

cout << fac << " ";

i++;

fac *= i;

}

13

14

15

cout << endl;

return 0;

}

ในตวอยางน โคดโดยใชคาสง while และ do while มการใชคาสงตางๆ คลายกนมาก แตใหระลกไววาไมใชทกกรณทจะเปนเชนน เราจงตองตรวจสอบผลรนของโคดเสมอ

6.3 คาสง for

นอกจากคาสง while และ do while แลว เราสามารถควบคมการวนซ าไดดวยคาสง for เชนกน ในคาสง while และ do while เราจะเหนไดวาในเกอบทกการวนซ าเราจะตองม

1) Initialization: การใหคาเรมตนกบตวแปรหนงตวหรอมากกวา เชน i = 0, sum = 0 2) Condition: เงอนไขในการวนซ า เชน i < n, i > 0 3) Update: การปรบคา (การอปเดตคา) เชน i++ หรอการอานคาจากแปนพมพ

คาสง for จะนาคาสงสาหรบการกระทาท ง 3 อยางมาไวในบรรทดเดยวกนตอนเรมตนเพอใหโปรแกรมอานและเขยนงายข น ทาใหการควบคมการวนซ าทาไดงายข น ในรปแบบของคาสง for ซงแสดงในรปท 9 เราจะเหนไดวามการใชคาวา for ซงแปลวาสาหรบ ตามดวยวงเลบ และในวงเลบมการใหคาเรมตน เงอนไข และการปรบคา ตามลาดบ และแตละอยางถกคนดวยเครองหมายเซมโคลอน (;) (สงเกตวาไมใชเครองหมายลกน า (,)) เราสามารถอานไดวา สาหรบการวนซ าน เรากาหนดใหมการต งคาเรมตนคอ … มเงอนไขในการวนซ าคอ … และมการปรบคาในแตละรอบคอ …

รปท 9 รปแบบการใชคาสง for

จากรปท 10 เราเหนการทางานของ for นนคอ

1) โปรแกรมจะตองต งคาเรมตนตามทเขยนไวในสวน initialization และจะทาแคคร งเดยวเทาน นกอนทจะเขาลป

2) โปรแกรมจะตรวจสอบเงอนไขตามทเขยนไวในสวน condition กอนทจะเขาลปคร งหนงกอน ถาเงอนไขเปนจรง ใหทาขอ 3 ถาเงอนไขเปนเทจ ใหจบการทางานของลปน

3) โปรแกรมจะทาคาสงทอยในลปตามลาดบ 4) จากน นโปรแกรมจะปรบคาทเขยนอยในสวน update หลงจากททาคาสงตางๆ และกอนทจะตรวจสอบ

เงอนไขอกคร งหนง 5) ทาซ าขอ 2)-4)

รปท 10 ผงงานการทางานของคาสง for

จากการทางานทอธบายไปขางตน เราจะเหนไดวาการทางานของคาสง for น นใกลเคยงกบการทางานของ while มาก ตางกนแควธเขยนเทาน นทแยกเอาการต งคาเรมตนและการปรบคาในแตละรอบออกมาเขยนในบรรทดแรก

ตวอยางท 10 การวนซ าเพอหาผลรวมโดยใชคาสง for

โจทย : จงเขยนโปรแกรมภาษา C++ เพอแสดงผลรวมของเลขจานวนเตมจาก 1-n ออกทางหนาจอโดยใชการวนซ าดวยคาสง for

1) เอาตพต คอผลรวมของเลขจานวนเตมจาก 1-n 2) อนพต คอจานวนเตม n 3) โจทยกาหนดใหใชการวนซ าดวยคาสง for 4) ไมมขอมลอะไรเพมเตม

เราเคยทาโจทยขอน ไปแลวในตวอยางท 3 ตวอยางท 6 และตวอยางท 7 แตขอน เราตองใชคาสง for เราจงเขยนโคดเหมอนกน แตเอา int i = 0 (initialization) และ i++ (update) มาไวในวงเลบหลง for ตามรปแบบ

โคด:

int main(){

int n, sum = 0;

cout << "Enter n: ";

cin >> n;

for(int i = 0; i < n; i++){

sum += i;

}

cout << "The sum of the first " << n << " integers is "

<< sum << endl;

return 0;

}

ขอบเขตของตวแปรทถกต งคาเรมตนในคาสง for

ในคาสง for เราสามารถประกาศตวแปรเพอใหคาต งตนในสวนของ initialization ไดเลย หรอเราจะประกาศตวแปรทจะใชกอนเขยนคาสง for แลวใหคาต งตนในสวนของ initialization ในคาสง for กได ความแตกตางของการเขยน 2 แบบน อยทขอบเขตของตวแปร ถาเราประกาศตวแปรในสวนของ initialization ขอบเขตของตวแปรจะอยในแค for เทาน น เราไมสามารถเอาตวแปรไปใชนอกลปได นนคอถาเราเอาตวแปรไปใชนอกลป โปรแกรมจะไมรจกตวแปรน นและจะทาใหคอมไพลไมผาน แตถาเราประกาศตวแปรกอนทจะเขา for เราจะสามารถใชตวแปรน นอกลปของคาสง for ได

ตวอยางท 11

เราสามารถเขยนโปรแกรมในตวอยางท 10 ไดอกแบบ ดงน

โคด:

1

2

int main(){

int n, sum = 0;

3

4

5

6

7

8

9

10

11

12

cout << "Enter a positive integer: ";

cin >> n;

for(int i=0; i < n/2; i++)

sum += i;

for(int i=n/2; i <= n; i++)

sum += i;

cout << "The sum of the first " << n

<< " integers is " << sum << endl;

return 0;

}

เราจะเหนไดวาตวแปร i ในคาสง for อนแรกทบรรทดท 5 กบตวแปร i ในคาสง for อนทสองทบรรทดท 7 ไมใชตวแปรตวเดยวกน เนองจากตวแปร i แรกถกประกาศใน initialization ของ for ตวแรก ทาใหขอบเขตของมนอยใน for ตวแรกเทาน น (จากบรรทดท 5 ถงบรรทดท 6) สวนตวแปร i ตวท 2 กเชนเดยวกน มนมขอบเขตแคจากบรรทดท 7 ถงบรรทดท 8 เทาน น แตถาเรามโปรแกรมดงน

โคด:

1

2

3

4

5

6

7

8

9

10

11

12

int main(){

int n, sum, i=0;

cout << "Enter a positive integer: ";

cin >> n;

for(sum = 0; i < n/2; i++)

sum += i;

for(i=n/2; i <= n; i++)

sum += i;

cout << "The sum of the first " << n

<< " integers is " << sum << endl;

return 0;

}

ตวแปร i ในโปรแกรมจะเปน i ตวเดยวกนหมด เพราะมนถกประกาศคร งเดยวทบรรทดท 2 นอกจากน ตวแปร sum ทใชใน for อนแรกทบรรทดท 6 และอนทสองทบรรทดท 8 เปนตวเดยวกน คอตวทประกาศไวในบรรทดท 2 ของโปรแกรมนนเอง แมวามนจะถกต งคาเรมตนไวในสวน initialization ของคาสง for แตเพราะมนประกาศกอนทจะเขา for เราจงสามารถใช sum ไดในสวนอนๆ ของฟงกชนเมน ในโคดตวอยางน คอใชในลปของคาสง for ตวทสอง

ตวอยางท 12

โจทย: จงหาความแตกตางของผลรนของโปรแกรมตอไปน

โคด 1:

1

2

3

4

5

6

7

8

9

int main() {

int i = 10;

cout << “begin “ << i << endl;

for(int i=0; i <= 20; i++)

cout << i;

cout << endl;

cout << "end loop " << i;

return 0;

}

ผลการทางาน 1:

Begin 10

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

end loop 10

โคด 2:

1

2

3

int main() {

int i = 10;

cout << “begin “ << i << endl;

4

5

6

7

8

9

10

for (i=0; i <= 20; i++)

cout << i;

cout << endl;

cout << "end loop " << i;

return 0;

}

ผลการทางาน 2:

Begin 10

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

end loop 21

ผลการทางานของโคดท งสองแบบน ตางกนแคทคา i ทแสดงออกทบรรทดท 9 หลงจากคาวา end loop ในโคดท 1 คา i ทบรรทดท 9 เปน 10 เหมอนตวทประกาศและแสดงออกทบรรทดท 3 เพราะมนเปนตวเดยวกน และไมไดถกเปลยนคาในลป for สวนตว i ทอยในลป for น น เปน i คนละตว เนองจากมนถกประกาศใหม ใชไดและเปลยนแปลงไดเฉพาะในขอบเขตของคาสง for เทาน น เมอพนจากขอบเขตของ for แลว i ตวน นกจะหายไป

สวนในโคดท 2 i ในคาสง for น นเปน i ตวเดยวกบทประกาศในบรรทดท 3 ซงจะถกใชไดและเปลยนแปลงไดทกทในฟงกชนเมนน ในคาสง for โปรแกรมไดมการใหคาเปน 0 ณ ตอนเรมตนการวนซ าทบรรทดท 5 จากน นi ถกเพมคาข นไปเรอยๆ และจบทคา 21 ซงทาใหลปจบเพราะคามนมากกวา 20 จากน นมนถกแสดงทบรรทดท 9 คาทไดจงเปน 21

ตวอยางท 13 การหาคาแฟกทอเรยล n ตวแรกโดยใชคาสง for

โจทย : จงเขยนโปรแกรมภาษา C++ เพอแสดงเลขแฟกทอเรยลจาก 1 ถง n โดยโปรแกรมจะทาการรบคา n เปนจานวนเตมผานทางแปนพมพ ใหทาสองแบบโดยใชคาสง for

1) เอาตพต คอเลขแฟกทอเรยลจาก 1! ถง n! 2) อนพต คอจานวนเตม n 3) โจทยกาหนดใหใชการวนซ าดวยคาสง for

4) ไมมขอมลอะไรเพมเตม

โคด:

int main(){

int n;

cout << "Enter a positive integer: ";

cin >> n;

cout << "Factorial numbers: ";

long fac = 1;

for(int i=1; i<=n; i++)

fac *= i;

cout << fac << " ";

}

cout << endl;

return 0;

}

เชนเดยวกบคาสง while และ do while เราสามารถเขยนโปรแกรมเพอควบคมการวนซ าตามคาปจจบนไดเชนกน ดงตวอยางตอไปน

ตวอยางท 14 การหาคาแฟกทอเรยลภายในคาทกาหนดให โดยใชคาสง for

โจทย: จงเขยนโปรแกรมภาษา C++ เพอแสดงเลขแฟกทอเรยลจาก 1 ถงคาแฟกทอเรยลทมคาไมเกน bound โดยโปรแกรมจะทาการรบคา bound เปนจานวนเตมผานทางแปนพมพ โดยใชคาสง for

1) เอาตพต คอเลขแฟกทอเรยลจาก 1 ถงคาแฟกทอเรยลทมคาไมเกน bound 2) อนพต คอจานวนเตม bound 3) โจทยกาหนดใหใชการวนซ าดวยคาสง for 4) ไมมขอมลอะไรเพมเตม

โคด:

int main(){

int bound;

cout << "Enter a positive integer: ";

cin >> bound;

cout << "Factorial numbers: ";

long fac = 1;

for(int i=2; fac < bound; i++)

cout << fac << " ";

fac *= i;

}

cout << endl;

return 0;

}

การปรบคา (update) แบบตางๆ ในคาสง for

จากตวอยางตางๆ ทเราเรยนมา การปรบคา (update) ในคาสง for น นเปนการปรบคาแบบเพมคาทละหนง (คอใช i++) แตในความเปนจรง เราสามารถปรบคาไดหลายแบบ เชนลดคาทละหนง (ใช i--) หรอเพมหรอลดคาทละมากกวา 1 เชนเพมคาทละสอง หรอลดคาทละสาม

ตวอยางท 15

โจทย : จงเขยนโปรแกรมภาษา C++ เพอรบคาจานวนเตม n ผานทางแปนพมพ แลวแสดงเลข n ถง 1 โดยคอยๆ ลดคาไปทละ 1 ผานทางหนาจอ โดยใชคาสง for

1) เอาตพต คอเลข n ถง 1 โดยคอยๆ ลดไปทละ 1 2) อนพต คอจานวนเตม n 3) โจทยกาหนดใหใชการวนซ าดวยคาสง for 4) ไมมขอมลอะไรเพมเตม

เราเคยเขยนโปรแกรมใหวนซ าจาก 1 ถง n โดยให i เรมจาก n แลวพมพ i โดยเพม i ไปทละหนงในแตละรอบ แตโจทยขอน เราตองการพมพจาก n ลดลงไปยง 1 เรากทาแบบเดยวกนแตแทนทเราจะเรมตนท 1 เรากเรมตนท n แลวลดคา i ไปทละหนง

โคด:

int main(){

int n;

cout << "Enter a positive integer: ";

cin >> n;

for(int i=n; i>0; i--){

cout << i << " ";

}

cout << endl;

return 0;

}

ตวอยางท 16

โจทย : จงหาผลรนของโปรแกรมตอไปน เมอโปรแกรมรบคา 10 ผานทางแปนพมพ

โคด:

1

2

3

4

5

6

7

8

9

int main(){

int n;

cout << "Enter a positive integer: ";

cin >> n;

if(n < 2)

cout << n << " is not prime.\n";

else if(n < 4)

cout << n << " is prime.\n";

else if(n%2 == 0)

10

11

12

13

14

15

16

17

18

19

20

21

cout << n << " = 2 * " << n/2 << endl;

else{

for(int d = 3; d <= n/2; d += 2)

if(n%d == 0){

cout << n << " = " << d <<" * " << n/d <<

endl;

exit(0);

}

cout << n << " is prime.\n";

}

return 0;

}

โปรแกรมน เปนโปรแกรมทแสดงวาจานวนเตม n ทรบเขามาเปนจานวนเฉพาะ (prime number) หรอไม โดยจานวนเฉพาะ (prime number) เปนจานวนทมเพยงแค 1 และตวมนเองเทาน นทหารมนลงตว โปรแกรมน ไดตรวจสอบ n ตามลาดบข นตอนดงน

1) n นอยกวา 2 หรอไม ถานอยกวา (คอเลข 1) กจะไมเปนจานวนเฉพาะ 2) n นอยกวา 4 หรอไม ถานอยกวา (คอเลข 2 และ 3) กจะเปนจานวนเฉพาะ 3) n หารดวย 2 ลงตวหรอไม ถาหารลงตวกไมเปนจานวนเฉพาะ 4) ถาไมเขาเงอนไขใดๆ แลว เรากจะทาการวนซ าจาก d=3 ถง d=n/2 ดวา n สามารถหารดวย d ตวใดได

ลงตวหรอไม โดยจะเพมคา d ทละสอง เนองจากเราจะไมตรวจสอบ d ทเปนเลขคเพราะถาหารดวยเลขคน นลงตว n กจะตองหารดวย 2 ลงตว ซงเราทาการตรวจสอบไปแลวในขอ 3) สวนการทเราหยด d ไวทครงหนงของจานวนทรบเขามา (n/2) เพราะวาไมม d ใดทมากกวาจานวนน แลวทจะสามารถหาร n ไดลงตว เมอส นสดลปน โดยทไมม d ใดหารลงตวแลว กแสดงวา n น นเปนจานวนเฉพาะ เพราะไมมจานวนเตมบวกใดหารลงตว นอกจาก 1 และตวมนเอง

ดงน น จากโจทยเมอโปรแกรมรบคา 10 ผานทางแปนพมพ กจะเขาเงอนไขในขอ 3) คอหารดวย 2 ลงตว เพราะฉะน นโปรแกรมจะใหผลรนวา 10 = 2*5

การหยดการวนซ าแบบอน

ในการเขยนการวนซ าดวยคาสง for เราไมจาเปนจะตองใสขอมลในสวนของ initialization, condition, update ใหครบกได เราสามารถควบคมการวนซ าดวยคาสง for ในทอนๆ ถาเราไมตองการใสคาใด กใหเราเวนคาน นวางไว แตเราตองมเครองหมายเซมโคลอน (;) ใหครบเสมอ เชนถาเราไมตองการใสคาเรมตนหรอคาอปเดต เรากสามารถเวนวางไวได โดยเขยน for( ; condition ; ) ถาเราไมตองการใสคาอะไรเลย เรากเขยนวา for( ; ; ) อยางไรกตาม ถาเราไมใสเงอนไขในการวนซ า ลปจะทาการวนซ าไปเรอยๆ ไมมทส นสด เราตองทาการหยดลปโดยใชคาสง break, exit(0), หรอ return ตามทเคยไดเรยนไปแลว

ตวอยางท 17

โจทย : จงเขยนโปรแกรมเพอรบเลขจานวนเตมผานทางแปนพมพ โดยใหวนซ ารบคาเขามาเรอยๆ จนวาอนพตจะมคาเทากบ 0 จากน นใหหาวาอนพตใดทมคามากทสด โดยใหใชคาสง for

1) เอาตพต คอคาอนพตทมากทสด 2) อนพต คอจานวนเตม n โดยวนรบคาเขามาจนกวาอนพตจะมคาเปน 0 3) โจทยกาหนดใหใชคาสง for 4) ไมมขอมลอะไรเพมเตม

ในขอน เราตองใชคาสง for แตวาเราไมสามารถอปเดตคาตามตวอยางทผานๆ มาไดเพราะเราไมทราบวาจะตองรบคาเขามากคา รแตเงอนไขทวาใหรบคาจนกวาอนพตจะมคาเปน 0 เทาน น ดงน นเราสามารถทจะท งตาแหนง update ของคาสง for ใหวางได

โจทยตองการใหเราหาคาทมากทสดในคาทผใชใสเขามาผานทางแปนพมพ ในการเขยนโคดน เราจงตองมตวแปรตวหนงเพอเกบคาทมากทสดในปจจบน กาหนดใหเปนตวแปร max เมอโปรแกรมอานคาจากผใชเขามา เราตองเอามาเปรยบเทยบกบคา max วาคาทเขามาใหมน นมากกวา max หรอไม ถาไมมากกวา แสดงวาคาทมากทสดทโปรแกรมเจอกยงเปนคา max อย แตถามากกวา แสดงวาคาทมากทสดทโปรแกรมเจอคอคาทอานเขามาใหม ดงน นโปรแกรมจงตองเปลยนคา max ใหเปนคาทเพงใสเขามา ดงแสดงในโคดตอไปน

โคด:

int main(){

int n, max;

cout << "Enter positive integers (0 to quit): ";

cin >> n;

for(max = n; n != 0;)

{

if(n > max) max = n;

cin >> n;

}

cout << "max = " << max << endl;

return 0;

}

ตวอยางท 18

โจทย : จงเขยนโปรแกรมเพอรบเลขจานวนเตมบวกผานทางแปนพมพ โดยใหวนซ ารบคาเขามาเรอยๆ จนวาอนพตจะมคาเทากบ 0 จากน นใหหาผลรวมของอนพตท งหมด โดยใหใชคาสง for แบบไมกาหนดคาใดๆ

1) เอาตพต คอผลรวมของอนพต 2) อนพต คอจานวนเตม n โดยวนรบคาเขามาจนกวาอนพตจะมคาเปน 0 3) โจทยกาหนดใหใชคาสง for แบบไมกาหนดคาใดๆ คอใชรปแบบ for( ; ; ) เราจงตองมการหยดลปดวย

คาสง break, exit(0) หรอ return 4) ไมมขอมลอะไรเพมเตม

โจทยขอน ใหหาผลรวมเชนเดยวกบทเราเคยทาไปแลว แตตางกนตรงทวา 1) ไมมการกาหนดรอบทแนนอน และ 2) คาทเอามารวมเปนคาตางๆ ทรบเขามาจากผใช อยางไรกตามโคดทเขยนกจะคลายเดม คอมการเกบผลรวมใน sum และบวกคาทรบเขามาจากผใชในแตละรอบ จนกวาผใชจะใสคา 0 เขามา เนองจากเราใชคาสง for แบบไมกาหนดเงอนไข ทาใหเราตองกาหนดเงอนไขในลปแทนเพอทจะใหลปน นหยดทางานเมอผใชใสอนพตเขามาเปน 0 ดงโคดขางลางน

โคด:

int main(){

int n, sum = 0;

cout << "Enter positive integers (0 or negative to quit):"

<< endl;

for(;;){

cin >> n;

if(n <= 0) break;

sum += n;

}

cout << "Sum = " << sum << endl;

return 0;

}

ถาเราเปรยบเทยบการใช for( ; ;) กบ while(true) ซงเปนการไมกาหนดเงอนไขการหยดลปหลงคาสงเชนกน เราจะไดโคดทคลายกนมากดงน

โคด:

int main(){

int n, sum = 0;

cout << "Enter positive integers (0 or negative to quit):"

<< endl;

while(true){

cin >> n;

if(n <=0) break;

sum += n;

}

cout << "Sum = " << sum << endl;

return 0;

}

ตวอยางท 19

โจทย : จงเขยนโปรแกรมเพอรบเลขจานวนเตมบวกผานทางแปนพมพ โดยใหวนซ ารบคาเขามาเรอยๆ จนวาอนพตจะมคาเทากบ 0 จากน นใหหาคาเฉลยของอนพตท งหมด โดยใหใชคาสง for แบบไมกาหนดคาใดๆ

1) เอาตพต คอผลรวมของอนพต 2) อนพต คอจานวนเตม n โดยวนรบคาเขามาจนกวาอนพตจะมคาเปน 0 3) โจทยกาหนดใหใชคาสง for แบบไมกาหนดคาใดๆ คอใชรปแบบ for( ; ; ) เราจงตองมการหยดลปดวย

คาสง break, exit(0) หรอ return 4) คาเฉลยคอผลรวมหารดวยจานวนอนพตทเรารบมาท งหมด เรามโคดของการหาผลรวมแลวในตวอยางท

18 เราเพยงแคจะตองเพมตวแปรเขาไปเพอนบวาเรามอนพตท งหมดกตว

โคด:

int main(){

int n, sum = 0;

cout << "Enter positive integers (0 or negative to quit):"

<< endl;

while(true){

cout << "\t" << count + 1 << " : ";

cin >> n;

if(n <= 0) break;

++count;

sum += n;

}

cout << "The average of those " << count <<

" positive numbers is " << float(sum)/count << endl;

return 0;

}

6.4 การวนซ าแบบซอน หรอการซอนลป (Nested loop)

ในเรองการเลอกทา (selection) เรามการเลอกทาแบบซอน (nested selection) คอการเอาคาสง if มาซอนกน ในเรองการวนซ าเรากมเชนกน เรยกวา การวนซ าแบบซอน (nested loop) หรอการซอนลป สาหรบบทเรยนน เราจะเรยนการซอนลปแค 3 ช น แตจะเนนทลป 2 ช น คอมลปช นนอก และลปช นใน ดงตวอยางในรปท 11 โดยกรอบใหญคอลปช นนอก และกรอบเลกคอลปช นใน

รปท 11 ตวอยางการวนแบบซอนหรอการซอนลป

โดยหลกการทางานของลปซอนลปคอมนจะทาซ าเปนจานวนเทากบ m x n รอบ เมอ m เปนจานวนรอบทตองทาของลปช นนอก และ n เปนจานวนรอบทตองทาสาหรบลปช นใน โดยการทางานจะเปนไปตามตารางท 4 นนคอโปรแกรมจะเขาไปในรอบแรกของลปช นนอกกอน ซงมลปช นในอย มนจะทาการวนซ าลปช นในใหครบ n รอบกอน จากน นจงเรมรอบทสองของลปช นนอก นนคอการวนซ าลปช นในใหครบ n รอบ ทาแบบน ไปเรอยๆ จนถงรอบท m (รอบสดทาย) ของลปช นนอก

ตารางท 4 การวนซ าของลปช นนอกและช นในในการซอนลป

ลปช นนอก รอบท 1 ลปช นในรอบท 1

ลปช นในรอบท 2

… ลปช นในรอบท n

ลปช นนอก รอบท 2 ลปช นในรอบท 1

ลปช นในรอบท 2 …

ลปช นในรอบท n

… …

ลปช นนอก รอบท m ลปช นในรอบท 1 ลปช นในรอบท 2

ลปช นในรอบท n

ตวอยางท 20 ตารางสตรคณ

โจทย : จงหาผลรนของโปรแกรมตอไปน

โคด:

1

2

3

4

5

6

7

8

9

10

11

#include <iomanip>

int main(){

for(int x = 1; x <= 12; x++){

for(int y = 1; y <= 12; y++){

cout << setw(4) << x * y;

}

cout << endl;

}

return 0;

}

โจทยขอน เปนคาสง for ซอนกน โดยช นนอกมการวนซ า 12 รอบและมคาสง endl ปดทาย (endl เปนคาสงทอยในลปช นนอก) สวนลปช นในกวนซ า 12 รอบเชนกน และมคาสงแสดงคาผลคณของ x และ y โดยไมมการเคาะบรรทด ดงน นในการวนรอบแรกของลปช นนอกและวนซ าลปช นในจนครบ 12 คร ง เราจะไดคาดงน

ตารางท 5 คา x, y และ x*y ในการวนรอบแรกของลปช นนอก

คา x คา y คา x * y 1 1 1

1 2 2

1 3 3 1 4 4

1 5 5 1 6 6

1 7 7

1 8 8 1 9 9

1 10 10

1 11 11 1 12 12

นนคอเราจะไดผลรนในรอบแรกเปน

1 2 3 4 5 6 7 8 9 10 11 12

จากน นในรอบทสองของลปช นนอกและวนซ าลปช นในจนครบ 12 คร ง เราจะไดคาดงน

ตารางท 6 คา x, y และ x*y ในการวนรอบทสองของลปช นนอก

คา x คา y คา x * y 2 1 2

2 2 4

2 3 6 2 4 8

2 5 10

2 6 12 2 7 14

2 8 16

2 9 18 2 10 20

2 11 22

2 12 24

นนคอเราจะไดผลรนถงรอบสองเปน

1 2 3 4 5 6 7 8 9 10 11 12

2 4 6 8 10 12 14 16 18 20 22 24

เมอโปรแกรมรนจนจบ เราจะไดเอาตพตคลายตารางสตรคณจากแม 1 ถงแม 12 ดงน

ผลการทางาน:

1 2 3 4 5 6 7 8 9 10 11 12

2 4 6 8 10 12 14 16 18 20 22 24

3 6 9 12 15 18 21 24 27 30 33 36

4 8 12 16 20 24 28 32 36 40 44 48

5 10 15 20 25 30 35 40 45 50 55 60

6 12 18 24 30 36 42 48 54 60 66 72

7 14 21 28 35 42 49 56 63 70 77 84

8 16 24 32 40 48 56 64 72 80 88 96

9 18 27 36 45 54 63 72 81 90 99 108

10 20 30 40 50 60 70 80 90 100 110 120

11 22 33 44 55 66 77 88 99 110 121 132

12 24 36 48 60 72 84 96 108 120 132 144

หมายเหต คาสง setw(4) เปนคาสงจดรปแบบการแสดงผลในไลบราร iomanip เปนคาสงทบอกวาใหจดการแสดงผลเปนบลอค บลอคละ 4 ตวอกขระ

ตวอยางท 21

โจทย: จงเขยนโปรแกรมเพอสรางผลรนออกทางหนาจอตามทกาหนดให

ตวอยางผลรน เมอใส 5 ผานทางแปนพมพ

5

*****

*****

*****

*****

*****

ตวอยางผลรน เมอใส 7 ผานทางแปนพมพ

7

*******

*******

*******

*******

*******

*******

*******

1) เอาตพต คอ”กลอง” ดอกจนแบบทบ จานวน n ตวในหนงบรรทดและจานวน n บรรทด 2) อนพต คอจานวนเตม n 3) โจทยไมไดกาหนดอะไรใหเพมเตม 4) ไมมขอมลเพมเตม

จากตวอยางทกาหนดให เราเหนไดวาหากผใชใส 5 ผานทางแปนพมพ เราจะไดดอกจน 5 ตวในหนงบรรทด และมจานวน 5 บรรทด แตหากผใชใส 7 ผานทางแปนพมพ เราจะไดดอกจน 7 ตวในหนงบรรทด และมจานวน 7 บรรทด แสดงวาคาทผใชใสเขามาเปนตวควบคมจานวนบรรทด และจานวนดอกจนในหนงบรรทด

โจทยขอน เราสามารถใชการวนซ าแบบซอนได โดยเราจะกาหนดใหลปช นนอกเปนตวควบคมจานวนบรรทดทตองวนซ า และกาหนดในลปช นในเปนตวควบคมจานวนดอกจนทตองวนซ าในแตละบรรทด ดงโคดตอไปน

โคด:

int main(){

cin >> n;

for(int x = 1; x <= n; x++){

for(int y = 1; y <= n; y++){

cout << '*';

}

cout << endl;

}

return 0;

}

ตวอยางท 22

โจทย: จงเขยนโปรแกรมเพอสรางผลรนออกทางหนาจอตามทกาหนดให

ตวอยางผลรน เมอใส 5 ผานทางแปนพมพ

5

*****

* *

* *

* *

*****

ตวอยางผลรน เมอใส 7 ผานทางแปนพมพ

7

*******

* *

* *

* *

* *

* *

*******

1) เอาตพต คอ”กลอง” ดอกจนแบบโปรง จานวน n ตวในหนงบรรทดและจานวน n บรรทด 2) อนพต คอจานวนเตม n 3) โจทยไมไดกาหนดอะไรใหเพมเตม 4) ไมมขอมลเพมเตม

จากตวอยางทกาหนดให เราเหนไดวาหากผใชใส 5 ผานทางแปนพมพ เราจะไดดอกจน 5 ตวในบรรทดแรกและบรรทดสดทาย และ 2 ตวทขอบกลองในบรรทดอนๆ (ตวทไมใชดอกจนคอ space หรอชองวาง) และมจานวน 5 บรรทด แตหากผใชใส 7 ผานทางแปนพมพ เ ราจะไดดอกจน 7 ตวในบรรทดแรกและบรรทดสดทาย และ 2 ตวทขอบกลองในบรรทดอนๆ (ตวทไมใชดอกจนคอ space หรอชองวาง) และมจานวน 7 บรรทด แสดงวาคาทผใชใสเขามาเปนตวควบคมจานวนบรรทด และจานวนดอกจนและจานวนชองวางในหนงบรรทด

โจทยขอน เราสามารถใชการวนซ าแบบซอนไดแบบขอทแลว โดยเราจะกาหนดใหลปช นนอกเปนตวควบคมจานวนบรรทดทตองวนซ า และกาหนดในลปช นในเปนตวควบคมดอกจนและชองวางทตองวนซ าในแตละบรรทด (ควบคมการพมพออกในแตละคอลมนนนเอง) เราจะเหนไดวาในขอน ตองมการกาหนดเงอนไข นนคอถาเปนบรรทดแรกหรอบรรทดสดทาย เราจะพมพดอกจนออกไปตามปกต แตถาเปนบรรทดอนน น เราตองดวาคอลมนใดพมพอะไร ซงกคอวาถาเปนคอลมนแรกและคอลมนสดทาย เราจะพมพดอกจนออก แตถาเปนคอลมนอนๆ เราจะพมพชองวางออกไป (ไมใชไมพมพเลย) ดงโคดตอไปน

โคด:

int main(){

cin >> n;

for(int x = 1; x <= n; x++){

for(int y = 1; y <= n; y++){

if(x==1 || x==n || y==1 || y==n)

cout << '*';

else

cout >> ' ';

}

cout << endl;

}

return 0;

}

การควบคมการวนซ าดวยคาสง break, continue และ goto

นอกจากจะรอใหลปหยดโดยรอใหเงอนไขเปนเทจแลว เราสามารถจะควบคมลปใหหยดหรอกระโดดขามคาสงตางๆ ได โดยใชคาสง break, continue และ goto โดยคาสงตางๆ ทาหนาทดงน

1) คาสง break จะหยดการทางานของลป ขามรอบทเหลอในลปช นน นท งหมดและทาคาสงทอยตอจากลปช นน น

2) คาสง continue จะขามคาสงทเหลอในลปช นในรอบน น เพอเรมลปรอบใหมทนท 3) คาสง goto จะกระโดดไปทาคาสงทปลายทางทนท

เพอใหเหนความแตกตางของคาสง break และ continue ใหพจารณาโคดตอไปน

โคด:

1

2

3

4

5

6

7

int main() {

for (int i = 0; i<10;i++) {

cout << "Top half :" << i << endl;

if (i > 5 ) break;

cout << "Bottom half:" << i << endl;

}

cout << "Outside of loop.";

return 0;

}

โคดน ทาการวนซ าจาก i=0 ถง i=9 โดยจะแสดงขอความวา Top half: ตอดวยคา i และ Bottom half: ตอดวยคา i แตถา i มากกวา 5 (ในทน คอ i=6) โปรแกรมกจะแสดงแค Top half: ตอดวยคา 6 แลวทาการจบลปทบรรทดท 4 และออกไปทาคาสงตอจากลปในบรรทดท 7 และจบโปรแกรม เรากจะไดผลรนดงน

ผลการทางาน:

Top half :0

Bottom half:0

Top half :1

Bottom half:1

Top half :2

Bottom half:2

Top half :3

Bottom half:3

Top half :4

Bottom half:4

Top half :5

Bottom half:5

Top half :6

Outside of loop.

ถาหากเราแทนทคาสง break ดวยคาสง continue โปรแกรมแคไมทาคาสงทเหลอในรอบท i > 5 (คอ i=6, 7, 8, 9) โดยจะแสดงแค Top half: ตอดวยคา i ในรอบเหลาน น แลวเรมรอบใหมเลย ดงน นโปรแกรมจะไดผลรนดงน

ผลการทางาน:

Top half :0

Bottom half:0

Top half :1

Bottom half:1

Top half :2

Bottom half:2

Top half :3

Bottom half:3

Top half :4

Bottom half:4

Top half :5

Bottom half:5

Top half :6

Top half :7

Top half :8

Top half :9

Outside of loop.

ดงน น เราจงตองระวงในการใชคาสง continue เพราะมนจะไมไดทาใหลปน นจบโดยส นเชง แตใหเรมการวนซ ารอบใหม อยางเชนถาหากเราเปลยนโคดเปนดงน

โคด:

1

2

3

4

5

6

7

8

9

10

int main() {

int i = 0;

while( i < 10) {

cout << "Top half :" << i << endl;

if (i > 5 ) continue;

cout << "Bottom half:" << i << endl;

i++; // be careful of this

}

cout << "Outside of loop.";

return 0;

}

เมอ i มคามากกวา 5 คอ i = 6 โปรแกรมจะไมทาคาสงทเหลอ ซงรวมถงการเพมคา i ในบรรทดท 7 ทาใหคา i คางอยท 6 และทาใหลปน วนซ าไปเรอยๆ ไมมทส นสด เพราะ 6 มคานอยกวา 10 เสมอ

ตวอยางท 23 การหยดลปช นเดยวดวยคาสง break และ continue

โจทย : จงหาผลรนของโปรแกรมตอไปน เมอปอน 4 5 6 และ 9 ผานทางแปนพมพตามลาดบ

โคด:

1

2

3

4

5

6

7

8

9

10

11

12

int main(){

int n;

for(;;){

cout << "Enter int: ";

cin >> n;

if(n % 2 == 0) continue;

if(n % 3 == 0) break;

cout << "\tBottom of loop.\n";

}

cout << "\tOutside of loop.\n";

return 0;

}

ในตวอยางน มท งคาสง break และ continue ทอยในลปไมรจบ (infinite loop) โดยใชคาสง for แบบไมมเงอนไข เรามาไลดการทางานของโปรแกรมกนไปทละอนพต อนพตแรกคอ 4 เมอ n เปน 4 จะทาใหเงอนไข n%2 == 0 เปนจรง โปรแกรมจะทาคาสง continue ซงแปลวาใหขามทกอยางทเหลอในลปรอบน น แลวเรมทาลปรอบใหมตอไป โปรแกรมกจะกลบไปทาบรรทดท 4 อกคร งและรบอนพตตวใหม อนพตตวทสองคอ 5 เมอ n เทากบ 5 กจะไมเขาเงอนไขใดเลย เพราะฉะน นโปรแกรมกจะพมพ Bottom of loop. ออกทางหนาจอ เปนอนจบลปในรอบน จากน นเมอข นรอบใหม อนพตเปน 6 กจะเขาเงอนไขในบรรทดท 6 อกคร ง โปรแกรมกจะขามทกอยางทเหลอในลปรอบน น แลวเรมลปรอบใหม แลวรบอนพตคอ 9 อนพตเทากบ 9 จะทาใหเงอนไข n%3 == 0 เปนจรง โปรแกรมจะทาคาสง break นนคอการหยดการวนซ าของลปน น ขามรอบทเหลอท งหมด แลวไปทาคาสงหลงจากการจบลปน นคอพมพ Outside of loop. ออกทางหนาจอ

ผลการทางาน:

Enter int: 4

Enter int: 5

Bottom of loop.

Enter int: 6

Enter int: 9

Outside of loop.

ตวอยางท 24 การหยดลปสองช นดวยคาสง break

โจทย : จงหาผลรนของโปรแกรมตอไปน

โคด:

1

2

3

4

5

6

7

8

9

10

11

12

13

#include <iomanip>

int main(){

for(int x = 1; x <= 12; x++){

for(int y = 1; y <= 12; y++){

if(y > x) break;

else

cout << setw(4) << x * y;

}

cout << endl;

}

return 0;

}

โคดในขอน คลายกบโคดใน

ตวอยางท 20 ยกเวนมคาสง break ในลปช นในเมอ y มากกวา x นนคอเราจะหยดทาลปช นในเมอ y มากกวา x แลวข นบรรทดใหม ตามคาสง cout << endl; ในบรรทดท 10 ซงเปนคาสงตอจากการวนลปช นใน จากน นเราจะทาลปช นนอกในรอบตอไป ผลจากรนจงไดดงน

ผลการทางาน:

1

2 4

3 6 9

4 8 12 16

5 10 15 20 25

6 12 18 24 30 36

7 14 21 28 35 42 49

8 16 24 32 40 48 56 64

9 18 27 36 45 54 63 72 81

10 20 30 40 50 60 70 80 90 100

11 22 33 44 55 66 77 88 99 110 121

12 24 36 48 60 72 84 96 108 120 132 144

เราลองมาไลโปรแกรมกนดสก 2-3 รอบ ในรอบแรกของลปช นนอก x เทากบ 1 จากน นกเขาลปช นในเรมท y เทากบ 1 ซงคา y <= x จงแสดงผลคณของ x และ y ออกทางหนาจอ ตอมา y เทากบ 2 ซงทาให y > x ลปช นในจงตองหยดทาทบรรทดท 6 และไปเคาะบรรทดทบรรทดท 10 แลวเรมลปช นนอกรอบท 2 ซง x เทากบ 2 และเรมลปช นในใหมอกคร ง โดยเรมจาก y เทากบ 1 ไปเรอยๆ จน y เทากบ 3 ซงทาให y > x ลปช นในจงตองหยดทาทบรรทดท 6 และไปเคาะบรรทดทบรรทดท 10 แลวเรมลปช นนอกรอบท 3 ซง x เทากบ 3 และเรมลปช นในใหมอกคร ง โดยเรมจาก y เทากบ 1 ไปเรอยๆ จน y เทากบ 4 ซงทาให y > x ลปช นในจงตองหยดทาทบรรทดท 6 และไปเคาะบรรทดทบรรทดท 10 แลวเรมลปช นนอกรอบท 4 ตอไป

ตวอยางท 25 การหยดลปสามช นดวยคาสง goto

โจทย : จงหาผลรนของโปรแกรมตอไปน

โคด:

1

2

int main(){

const int N = 5;

3

4

5

6

7

8

9

10

11

12

13

14

for(int i = 0; i < N; i++){

for(int j = 0; j < N; j++){

for(int k = 0; k < N; k++){

if(i + j + k > N) goto esc;

else cout << i + j + k << " ";

} // for k

cout << "* ";

} // for j

esc: cout << "." << endl;

} // for i

return 0;

}

โจทยขอน มลป 3 ช น คอช นนอก (ควบคมโดย i) ช นกลาง (ควบคมโดย j) และช นใน (ควบคมโดย k) และมการใชคาสง goto ทลปช นในในบรรทดท 6 ซงเปนคาสงใหกระโดดไปทาคาสงทปลายทาง ในทน คอสวนของโปรแกรมทชอวา esc ซงอยในลปช นนอกทบรรทดท 11 เงอนไขในการกระโดดคอเมอผลรวมของ i, j และ k น นมากกวา N กใหออกไปท esc ซงหมายความวาใหหยดทาลปช นในและกลางไปเลย แลวพมพจด ( .) ในบรรทดท 11 กอนเรมลปช นนอกรอบใหม สาหรบลปช นในถาผลรวมของ i, j และ k ไมมากกวา N เราจะพมพผลรวมออก และพอหมดลปช นในแลว โปรแกรมจะพมพเครองหมายดอกจน (*) ในบรรทดท 8 ซงเปนคาสงของลปช นกลาง กอนจะเรมลปช นกลางรอบตอไป เราจะไลคาของตวแปรในโปรแกรมใหดดงน

ตารางท 7 คาของ i, j, k, i+j+k และผลทแสดงออกทางหนาจอในแตละรอบของลป 3 ช น

คา i คา j คา k i + j + k cout 0 0 0 0 0

0 0 1 1 1

0 0 2 2 2 0 0 3 3 3

0 0 4 4 4 จบลปช นในเพราะ

k >= N *

0 1 0 1 1

คา i คา j คา k i + j + k cout

0 1 1 2 2 0 1 2 3 3

0 1 3 4 4

0 1 4 5 5 จบลปช นในเพราะ k

>= N *

0 2 0 2 2

0 2 1 3 3

0 2 2 4 4 0 2 3 5 5

0 2 4 6 (i+j+k > N)

. (เคาะบรรทด)

จบลปช นกลางเพราะโดนขามไป

จบลปช นในเพราะโดนขามไป

1 0 0 1 1

1 0 1 2 2 1 0 2 3 3

1 0 3 4 4

1 0 4 5 5 จบลปช นในเพราะ

k >= N *

1 1 0 2 2

1 1 1 3 3

1 1 2 4 4 1 1 3 5 5

1 1 4 6 (i+j+k > N)

. (เคาะบรรทด)

คา i คา j คา k i + j + k cout

จบลปช นกลางเพราะโดนขามไป

จบลปช นใน เพราะโดนขามไป

2 0 0 2 2

2 0 1 3 3 2 0 2 4 4

2 0 3 5 5 2 0 4 6

(i+j+k > N) .

(เคาะบรรทด)

จบลปช นกลางเพราะโดนขามไป

จบลปช นใน เพราะโดนขามไป

3 0 0 3 3 3 0 1 4 4

3 0 2 5 5

3 0 3 6 (i+j+k > N)

. (เคาะบรรทด)

จบลปช นกลางเพราะโดนขามไป

จบลปช นใน เพราะโดนขามไป

4 0 0 4 4 4 0 1 5 5

4 0 2 6 (i+j+k > N)

. (เคาะบรรทด)

จบลปช นกลางเพราะโดนขามไป

จบลปช นใน เพราะโดนขามไป

จบลปช นนอกเพราะ i >= N

จากคาทไลมาในตาราง เราไดผลรนดงน

ผลการทางาน:

0 1 2 3 4 * 1 2 3 4 5 * 2 3 4 5 .

1 2 3 4 5 * 2 3 4 5 .

2 3 4 5 .

3 4 5 .

4 5 .

การใชธง (flag) ในการหยดลป

นอกจากจะหยดการวนซ าดวยเงอนไข คาสง break, continue และ goto แลว เรายงสามารถหยดลปโดยการใชธง (flag) ซงโดยปกตเราจะใชตวแปรชนดบลนทมคาจรงหรอเทจเปนธง เชน ถาเราเจอสงทเราตองการแลว เรากต งคาธงของเราใหเปนจรง ตามตวอยางตอไปน

ตวอยางท 26

โจทย : จงหาผลรนของโปรแกรมตอไปน

โคด:

1

2

3

4

5

6

7

8

9

10

11

int main(){

const int N = 5;

bool done = false; // done is a flag

for(int i = 0; i < N; i++){

for(int j = 0; j < N && !done; j++){

for(int k = 0; k < N && !done; k++){

if(i + j + k > N) done = true;

else cout << i + j + k << " ";

} // for k

cout << "* ";

} // for j

12

13

14

15

16

cout << "." << endl;

done = false; // reset flag

} // for i

return 0;

}

อนทจรง ผลรนของตวอยางน เหมอนกบผลรนของตวอยางทแลว เพยงแตมวธหยดลปทตางกน ในตวอยางทแลว ลปหยดดวยคาสง goto แตในโคดน เราหยดลปดวยการใชธง (flag) นนคอเรากาหนดตวแปรชนดบลน (boolean) ข นมาหนงตวแลวต งคาเปนเทจ (false) กอน และในการวนซ าเราจะต งเงอนไขวายงใหวนทาซ าอยตราบใดทตวแปรธงตวน ยงเปนเทจ เมอเราเจอเงอนไขทจะตองหยดลป เราจะเปลยนคาของตวแปรธงตวน เปนจรง (true) กจะทาใหในรอบตอไปน นจะไมมการวนซ าอก

อยางไรกตาม ขอควรระวงในการใชตวแปรธงน คอ การรเซตคาตวแปรใหกลบเปนเทจเหมอนเดมเมอจาเปน เราจะตองวางใหถกทดวย ไมเชนน นลปกจะไมหยด หรอหยดผดจงหวะ ไมเปนไปตามทเราตองการ

สรปคาสงในการหยดลป

คาสงทหยดการทางานของลป มดงน

- break; หยดลปปจจบนไปเลย ขามรอบทเหลอท งหมดและออกจากลป - exit(0); ออกจากฟงกชนปจจบนไปเลย - return 0; ออกจากฟงกชนปจจบนไปเลย - goto somewhere; กระโดดขามไปยงตาแหนงทกาหนดใหทนท - ใชตวแปรธง done = true/false; วนซ าเปนปกต จงตองกาหนดใหเงอนไขการวนซ าข นอยกบธงดวย

คาสงทเรมลปรอบใหมทนท มดงน

- continue; จบการทาลปรอบน น ขามคาสงทเหลอในรอบน น แลวเรมลปรอบใหม - goto somewhere; กระโดดขามไปยงตาแหนงทกาหนดใหทนท

สรปสงทควรจะเขาใจในบทเรยน

1) การวนซ าหรอการลป คอการทาคาสงหรอบลอคของคาสงซ าไปซ ามาจนกวาเงอนไขในการวนซ าจะเปนเทจ

a. วนซ าเปนจานวนรอบทแนนอน จะมการใชตวนบ (counter) และการปรบเปลยนคาของตวนบในแตละรอบ

b. วนซ าโดยไมกาหนดรอบทแนนอน มการวนซ าไปเรอยๆ จนกวาจะไดคาของตวแปรทตองการ จะตองมการปรบคาของตวแปรทเปนเงอนไข อาจจะโดยการคานวณตางๆ

c. วนซ าโดยไมกาหนดรอบทแนนอน มการวนซ าไปเรอยๆ โดยการกาหนดเงอนไขจากคาทผใชรบผานทางแปนพมพ

2) คาสงในการวนซ าในภาษา C++ คอ a. while b. do while c. for

3) ถาเงอนไขในการวนซ าเปนจรงเสมอ หรอไมไดกาหนดเงอนไข เชน while(true) และ for( ; ;) เราสามารถทาใหลปหยดไดโดยคาสง break, exit(0), return หรอ goto