วันอาทิตย์ที่ 5 มิถุนายน พ.ศ. 2559

เริ่มต้นใช้งานอาดุยโน่ : บทที่ 6 โครงสร้างการวนซ้ำ (loop statement)

สำหรับคนที่ไม่เคยอ่าน ให้ไปไล่อ่านบทแรกๆก่อนนะครับ เพราะเทคนิคการเขียนโปรแกรมต่างๆ เราจะไม่พูดซ้ำ

http://menglab.blogspot.com/p/blog-page_45.html


เอาหล่ะ เริ่มเลยละกัน
เรารู้ว่าการทำงานของฟังก์ชัน loop คือการวนซ้ำที่มีให้ในโปรแกรม  แล้วถ้าเราต้องการการวนซ้ำเพียงบางส่วนของโปรแกรมหละ.....?



ซึ่งเราก็สามารถทำได้โดยการใช้โครงสร้างการวนซ้ำ หรือลูป (loop)  ซึ่งเราจะสอนแค่สองประเภทในเบื้องต้นก่อน คือ while และ for

การใช้งานคำสั่ง while

while นั้นมีโครงสร้างและการใช้งานทั่วไปเหมือน if นั่นคือ


while(ค่าเงื่อนไข){การทำงาน}

ซึ่งสำหรับค่าเงื่อนไข และการทำงานนั้นเหมือนของ if ทุกประการ คือการเริ่มต้นคำสั่ง ตรวจสอบค่าเงื่อนไข และเริ่มทำงานที่ปีกกาเปิด จนจบที่ปีกกาปิด เพียงแต่หลังจากที่ทำงานจบแล้ว มันจะกลับไปตรวจสอบค่าเงื่อนไข ซึ่งถ้าเงื่อนไขยังเป็นจริงอยู่ มันจะก็เริ่มทำงานใหม่ไปเรื่อยๆจนกว่าเงื่อนไขจะเป็นเท็จ เช่น





เราคงจำได้จากตัวอย่าง hello world ซึ่งถ้าเราใส่คำสั่งไว้ใน setup มันจะทำงานเพียงครั้งเดียว  แต่ในกรณีนี้ เราใส่ while ทำให้มันวนซ้ำๆ


ทีนี้ผู้อ่านคงสงสัยว่า ถ้าอย่างนั้นจะทำให้มันหลุดออกจากเงื่อนไขได้อย่างไร  เพราะไม่ว่าจะใส่เงื่อนไขอย่างไร ก็ยังเกิดการวนซ้ำ


ซึ่ง คำตอบก็คือ เราต้องทำให้เงื่อนไขมันผิด โดยการอัพเดทค่าตัวแปร



จะเห็นว่า ค่าตัวแปรนั้น น้อยลงไปเรื่อยๆ กระทั้งค่าไม่มากกว่า 0 นั่นก็คือค่า 0 ก็จะหลุดออกจาก while
ถ้าเราไล่อ่านการทำงานของโค๊ดทีละบรรทัด เราจะเห็นว่าการทำงานมีดังนี้
1. กำหนดค่าตัวแปร a เท่ากับ 5
2. คำสั่ง while จะตรวจสอบว่า a มากกว่า 0 หรือไม่ ผลคือเป็นจริง
3. แสดงค่า a บนมอนิเตอร์ ซึ่งก็คือ 5
4. a = a -1 จะได้ a = 5-1 ก็คือการกำหนดค่าใหม่ของ a เป็น 4 และสิ้นสุดการทำงานของ while
5. กลับไปตรวจสอบเงื่อนไขว่า a>0 หรือไม่ ซึ่ง  a มีค่าเท่ากับ 4 ทำให้เงื่อนไขเป็นจริง แล้วจะกลับไปทำงานแบบข้อสาม ซึ่งผลคือ แสดงค่า และค่าก็ลดลงเรื่อยๆ  จนถึง 0
6.เมื่อกลับไปตรวจสอบเงื่อนไข  a>0  อีกครั้ง และ a มีค่าเป็น 0 ทำให้เงื่อนไขเป็นเท็จ จึงหลุดจากการวนซ้ำของ while


ประโยชน์ของ while ในเบื้องต้น
1.ใช้สร้างการวนซ้ำแบบนับจำนวนรอบ จากตัวอย่าง ถ้าเราเปลี่ยนการแสดงค่า a เป็นการแสดงค่าว่า "Hello" ก็จะได้การแสดงค่าซ้ำห้าครั้ง

2. สามารถอัพเดทค่าให้อยู่ในช่วงต่างๆได้ หรือกฎคือการรันค่าจากค่าหนึ่ง ถึงอีกค่าหนึ่ง เช่น กำหนดให้แสดงค่า 20 ถึง 50  ผ่านซีเรียล

3.ใช้ในลักษณะการวนซ้ำจนกว่าจะเข้าเงื่อนไข

Tool Tips

ในการเพิ่มลดค่าตัวแปรด้วย 1 เช่น  a = a+1; หรือ a = a-1; นั้นสาสามรถเขียนในลักษณะของ a++;(เพิ่มค่า  a ขึ้น 1) หรือ a--; (ลดค่า a ลงหนึ่ง) ได้


การใช้งานคำสั่ง for

การใช้ for จะสะดวกในการนับค่าจากค่าจากค่าหนึ่ง ถึงอีกค่าหนึ่ง โดยมีโครงสร้างดังนี้


for( ค่าเริ่มต้น;ค่าเงื่อนไข;การเพิ่มลด){การทำงาน}



ตัวอย่างการใช้งาน





ซึ่ง for นั้น เหมาะที่จะใช้ในการรันตามจำนวนครั้ง หรือรันเลขจากค่าหนึ่งถึงอีกค่าหนึ่งคล้ายกับ while แต่จะไม่เหมาะกับการวนซ้ำตามเงื่อนไข ซึ่งถ้าเราเปลี่ยนคำสั่งจาก for  เป็น while จะได้ดังนี้




เราจะสังเกตเห็นสิ่งที่มีร่วมกันของทั้งสองแบบ  ก็ให้เลือกใช้ตามความเหมาะสม

นอกจากนี้เราสามารถประกาศตัวแปรในส่วนของค่าเริ่มต้นได้ เช่น

แต่ตัวแปรนั้น จะสามารถใช้ได้ในขอบเขตการทำงานของ for เท่านั้น

Tool Tips
1.ถ้าเราต้องการวนซ้ำเป็นจำนวนรอบ โดยไม่สนใจค่าตัวแปร สามารถทำได้โดย
for(int a = 0;a<(จำนวนรอบ);a++){   }

2. ถ้าเราต้องการรันเลขจากค่าๆหนึ่งไปยังค่าอีกค่าหนึ่ง สามารถทำได้โดย
for(int a = (ค่าเริ่มต้น);a<= (ค่าสุดท้าย);a++){  } 
ในกรณีที่นับจากน้อยไปมาก และ

for(int a = (ค่าเริ่มต้น);a>= (ค่าสุดท้าย);a--){  }   
ในกรณีที่นับจากมากไปน้อย และ


ข้อควรระวัง
จำนวนรอบสูงสุดที่ for จะนับได้ ขึ้นกับขนาดของตัวแปรที่นำมาใช้ด้วย


การใช้งานคำสั่ง break , continue

ในการออกจากการวนซ้ำ นอกจากการผิดเงื่อนไขแล้ว ยังมีอีกวิธีหนึ่งคือ break; ซึ่งเป็นคำสั่งในการบังคับให้ออกจากการวนซ้ำทันที

ลักษณะในการใช้งานส่วนใหญ่จะใช้กับ while (แต่ก็สามารถใช้กับ for ได้เช่นกัน)โดยให้เงื่อนไขในคำสั่ง while นั้น เป็นจริงเสมอ จากนั้นใส่เงื่อนไขที่จะใช้ break ดังที่แสดงในตัวอย่าง



นอกจากนี้ ยังมีคำสั่งที่ใช้ข้ามการทำงานรอบนั้นๆ นั่นก็คือ  continue

การทำงานของ continue ก็คือ การจบการทำงานของรอบนั้นๆ ทันที ทำให้ while หรือ for จะกลับไปตรวจสอบเงื่อนไขอีกครั้ง ก่อนที่จะวนซ้ำ หรือออกจากการวนซ้ำ

ลักษณะการใช้งาน มักจะใช้งดเว้นการกระทำบางอย่าง เพราะคำสั่งที่อยู่หลังจากการใช้  continue จะถูกข้ามทั้งหมด  ยกตัวอย่างเช่น


จากตัวอย่างเราจะเห็นว่า ไม่มีการทำงาน(การแสดงค่า) เมื่อ a > 5 และ a < 8 เพราะมันถูกข้ามไปนั่นเอง


แบบฝึกหัด

1. ให้แสดงค่า 10 ถึง 20 ตามลำดับบนซีเรียลมอนิเตอร์ จากนั้นแสดงค่า 20 ถึง 10

2. แสดงสูตรคูณแม่ 3 ใน 12 ลำดับ (3x1 ถึง 3x12)

3. หาผลบวกของสูตรคูณแม่ 13  ใน 12 ลำดับ (13 + 26 + 39 .....)

4. แสดงเลขฟิโบนักชี 10 ลำดับ (1,1,2,3,5,8,13...)

5. ให้ซีเรียลมอนิเตอร์ปริ้นค่าดังนี้ (ใช้ for)
*
**
***
****
....
จำนวนสิบขั้น

6.ให้แสดงค่าจำนวนเฉพาะที่อยู่ช่วงตั้งแต่ 1 - 50 (ใช้เรื่อง % มอดดูโล อยู่ท้ายบทที่ 4)

7.เขียนโปรแกรมแสดงเลขที่อยู่ในช่วง 0 ถึง 100 และ 3 หารลงตัว (ใช้เรื่อง % มอดดูโล อยู่ท้ายบทที่ 4)

8. ให้โปรแกรมแสดงเลขสองเลข(คั่นด้วยลูกน้ำ) แสดงแต้มที่เป็นไปได้เมื่อโยนลูกเต๋าสองลูก

จะเฉลยไว้ในคอมเม้นเมื่อมีคนถามนะครับ  ขอให้ลองพยายามทำดูก่อน

9.แสดงเลข 0 - 100 ยกเว้นเลขที่หารด้วย 7 ลงตัว


การใช้งานคำสั่ง

เมื่อเรามองโปรแกรมเป็นชุดลำดับของคำสั่ง เมื่อเราจัดให้หนึ่งบรรทัดมีหนึ่งคำสั่งเท่านั้น โปรแกรมธรรมดา จะทำงานจากบนลงล่าง ไล่ที่ละคำสั่ง 1 ,2 ,3 ,4 ...  จนจบโปรแกรม  แต่โปรแกรมที่มี control structor จะไม่เป็นแบบนั้น เพราะบางบรรทัดอาจจะไม่ได้ทำ หรืออาจมีการวนซ้ำ เช่นจากบรรทัดที่ 5 แล้วกลับไปบรรทัดที่ 2 อีก เป็นต้น
ซึ่งการกำหนดตำแหน่งที่โปรแกรมรันไปนั้น จะถูกกำหนดโดยอ้อมๆจากฟังชั่นเหล่านี้ เช่น เมื่อการทำงานของ while จบแล้วจะกลับไปเริ่มคำสั่ง while ซ้ำอีก เป็นต้น

แต่คำสั่ง goto นั้นต่างออกไป...

การใช้งานคำสั่ง goto
goto ชื่อlabel;

การประกาศ label
ชื่อlabel :

**การตั้งชื่อ label ใช้กฎเหมือนตัวแปร
**สามารถประกาศได้แค่ที่เดียว ต่อ 1 ชื่อ
**การเรียกใช้ goto จะต้องอยู่ในฟังก์ชั่นเดียวกับ label
คำสั่ง goto นั้น เป็นเหมือนประตูมิติ ที่จะกำหนดเลยว่า ถ้าได้รับคำสั่งนี้ จะต้องไปโผล่ตรงนี้ ลองดูตัวอย่างกัน




จากตัวอย่าง จะเห็นว่า it here อยู่ใน if ซึ่งเงื่อนไขเป็นเท็จ โดยทั่วไป จะไม่มีทางทำคำสั่งนี้
แต่เนื่องจากเราแปะป้าย หรือ label หรือก็คือประตูวาร์ปไว้  นึกถึงห้องปิดตายที่ไม่มีทางเข้าได้ แต่เราวาร์ปเข้าไปนั่นแหละ เมื่อ a  นับมาถึง 6 ก็จะเข้าเงื่อนไข และเรียกใช้คำสั่ง goto  และทำให้ for นั้น ถูกยุติไปโดยปริยาย


นอกจากนี้ เรายังสามารถใช้  goto ให้ทำงานในลักษณะของ while ได้อีกด้วย




เพราะเรารู้ว่า while จะเช็คเงื่อนไขก่อนทำงาน พอทำงานจบ โปรแกรมจะกลับไปเช็คเงื่อนไขอีกครั้ง ทำให้เราสามารถเขียน while โดยใช้ if และ goto ได้

ข้อควรระวัง
การใช้งาน goto นั้น จะไม่มีขอบเขต  นั่นคือสามารถทำลาย loop หรือโครงสร้างอื่นๆได้ ดังนั้นจึงทำให้โปรแกรมสามารถแก้ไขได้ยาก จึงไม่แนะนำให้เอาไปใช้จริง เพียงแต่ใช้เพื่อการศึกษาเท่านั้น

การใช้งานคำสั่ง switch case

switch (ตัวแปร){
case ค่าเปรียบเทียบ : การทำงาน;
}


ตัวอย่าง


อันที่จริง switch case นั้น อยู่ในหมวดของโครงสร้างเงื่อนไข แต่ผมคิดว่าสอน goto ก่อนน่าจะเห็นภาพมากกว่า  ซึ่งเมื่อคำสั่งทำงาน  case แต่ละ  case ก็จะเหมือน label ถ้าค่าของตัวแปรนั้นตรงกับค่าของ case ไหน โปรแกรมก็จะเริ่มทำงานที่ case นั้น ซึ่งในที่นี้คือ 3 จากนั้นก็จพทำงานลงมาตามลำดับโดยไม่สนใจคำว่า case นั่นคือการปริ้นค่า 4 5 ลงมาเรื่อยๆ

ในกรณีที่ไม่มีค่าใดตรงกับค่าของตัวแปรเลย จะไม่มีการทำงาน แต่เราสามารถเพิ่ม default  เข้าไปได้
ซึ่งโปรแกรมจะกระโดดมาที่ default เมื่อตัวแปรไม่เท่ากับค่าของ case ไหนเลย


ข้อควรระวัง
ค่าของ case ต้องไม่ซ้ำกัน และอย่างที่บอกว่า การทำงานของ switch นั้นเหมือนกับ goto พอมันกระโดดไปทำงานแล้ว ก็จบแค่นั้น โปรแกรมจะทำงานตามลำดับโดยที่คำว่า case หรือ default ไม่มีความหมาย จนจนการทำงาน แล้วก็ออกจากคำสั่งไป


การประยุกต์ใช้
สามารถใช้แทน if/else ที่เลือกเงื่อนไขกรณีจากตัวแปร ตัวแปรเดียวได้
แต่เนื่องจาก หลังจากเจอ case ที่มีค่าตรงกันแล้ว โปรแกรมจะทำงานต่อมาเรื่อยๆ จนไปเข้า case  อื่นๆด้วย

ดังนั้น จึงเอาคำสั่ง break มาใช้ขั้นทุกๆครั้งที่คำสั่งของ case นั้นๆสิ้นสุดลง ยกเว้นตัวที่อยู่ล่างสุดของคำสั่ง switch จะใส่หรือไม่ใส่ก็ได้


จะเห็นว่า โปรแกรมไม่ทำงานในส่วนของ case อื่นๆแล้ว

8 ความคิดเห็น:

  1. ส่งการบ้าน ข้อ2ครับ

    int a = 3;
    int b = 1;
    int c;
    void setup() {
    Serial.begin(9600);
    for (b; b <= 12; b++) {
    c = a * b;
    Serial.print("3 X ");
    Serial.print(b);
    Serial.print(" = ");
    Serial.println(c);
    }
    }


    void loop() {

    }
    ข้อ 3 งงก่อนครับ คิดออกเด๋วมาส่ง มีใบ้มั้ยครับ แหะ ๆ ๆ

    ตอบลบ
    คำตอบ
    1. มีครับผม ลองประกาศตัวแปรอีกตัว
      ผมจะใบ้ให้ว่า
      c = c+a;

      ลบ
  2. ส่งงาน ข้อ 3 แบบ มั่วๆครับ อ.เม้ง


    int a = 3;
    int b = 1;
    int c;
    int d;
    void setup() {
    Serial.begin(9600);
    for (b; b <= 12; b++) {
    c = a * b;
    if (b == 12) {
    goto total;
    }
    Serial.print("3 X ");
    Serial.print(b);
    Serial.print(" = ");
    Serial.println(c);
    if (0) {
    total :
    d = a + a * 2 + a * 3 + a * 4 + a * 5 + a * 6 + a * 7 + a * 8 + a * 9 + a * 10 + a * 11 + a * 12;
    Serial.println();
    Serial.println("#####################");
    Serial.print("ผลรวมของผลคูณเท่ากับ");
    Serial.print("=");
    Serial.println( d);
    }
    }
    }

    void loop() {
    // put your main code here, to run repeatedly:

    }
    http://picture.in.th/id/832c34fc34bc50fc6182a27e50f3a9a2

    ตอบลบ
    คำตอบ
    1. ยังผิดอยู่นะครับ ตรง
      d = a + a * 2 + a * 3 + a * 4 + a * 5 + a * 6 + a * 7 + a * 8 + a * 9 + a * 10 + a * 11 + a * 12;
      มันสามารถใช้การวนลูปทำได้

      ลบ
    2. ผมว่ายังไงก็ใช่ได้หมดน่ะครับไม่มีอันไหนที่ตายตัวแล้วแต่คนถนัดน่ะครับ

      ลบ
    3. มันเป็นการฝึกประยุกต์ใช้หนะครับ
      ถ้าใช้วิธีนี้ ผมให้บวกซักร้อยลำดับก็ตายสิครับ 5555+

      ลบ
  3. ความคิดเห็นนี้ถูกผู้เขียนลบ

    ตอบลบ