การเลือกและการวนซ้ำ
แนะนำใหม่| English | ไทย |
|---|---|
| selection/sɪˈlekʃn/ | การเลือก |
| iteration/ˌɪtəˈreɪʃn/ | รอบการทำงาน |
| trace table/treɪs ˈteɪbl/ | ตารางติดตาม |
| nested/ˈnestɪd/ | แบบซ้อนกัน |
| logic error/ˈlɒdʒɪk ˈerə/ | ความผิดพลาดด้านตรรกะ |
| count-controlled loop/kaʊnt kənˈtrəʊld luːp/ | ลูปควบคุมด้วยนับ |
| array/əˈreɪ/ | arreglo (อาเรย์/ชุดข้อมูลแบบตาราง) |
| pre-condition loop/priː kənˈdɪʃn luːp/ | ลูปก่อนเงื่อนไข |
| post-condition loop/pəʊst kənˈdɪʃn luːp/ | ลูปหลังเงื่อนไข |
| dry run/draɪ rʌn/ | การรันแบบแห้ง |
บรรทัดเกินมาหนึ่งบรรทัด
- ในปี 2014 Apple ส่งอัปเดตความปลอดภัยเนื่องจากบรรทัดซ้ำเพียงบรรทัดเดียว ลึกอยู่ในโค้ดที่ตรวจสอบ certificate ของเว็บไซต์,
goto fail;ปรากฏสองครั้งติดกัน - สำเนาที่สองอยู่นอก
IFของมัน, ดังนั้นจึงทำงานทุกครั้ง และการตรวจสอบด้านล่างไม่เคยทำงาน เป็นเวลาหลายเดือน ผู้โจมตีสามารถปลอมตัวเป็นเว็บไซด์ใดก็ได้ - Selection และ iteration คือโครงสร้างที่ตัดสินใจว่าอะไรจะทำงานและ多少次. ทำผิดแค่บรรทัดเดียวโปรแกรมก็ยังทำงานอยู่ เพียงแต่ทำงานผิด
- บทเรียนนี้คือ IF, CASE และลูปทั้งสาม, และตาราง trace ที่จับข้อผิดพลาดได้ก่อนการสอบ
Selection
IF age >= 18 THEN … ELSE … ENDIF
ELSEเป็น option,ENDIFไม่ใช่ ทุกIFต้องปิด- Condition คือ Boolean expression ใดๆ: การเปรียบเทียบ, หรือการเปรียบเทียบที่เชื่อมด้วย
AND,ORและNOT

*An IF … ELSE ตรวจสอบครั้งเดียว แล้วทำงาน exactly หนึ่ง branch
Nested IFs และ boundaries
- A nested IF คือ IF ภายใน branch ของอีก IF หนึ่ง, และแต่ละตัวต้องการ
ENDIFของตัวเอง - ขอบเขตคือจุดที่คะแนนถูกหัก "คะแนน 50 ขึ้นไปผ่าน" คือ
Mark >= 50, ไม่ใช่Mark > 50. - การเปรียบเทียบที่ผิดเป็น ความผิดพลาดด้านตรรกะ: โปรแกรมรันได้แต่ให้คำตอบผิดสำหรับบางอินพุต การใช้ Trace กับค่าขอบเขต เช่น ตัวเลข 50 เอง เป็นวิธีหาข้อผิดพลาดนี้
"คะแนน 50 ขึ้นไป ผ่าน" เขียนเป็น IF Mark ____ 50 THEN
"หรือมากกว่า" รวมถึง 50 เอง ดังนั้นการเปรียบเทียบคือมากกว่าหรือเท่ากับ > จะทำให้นักเรียนสอบตกที่ 50 พอดี
กรณี
CASE OF Grade … ENDCASEทดสอบ ค่าเดียว เทียบกับตัวเลือกหลายตัว และดูสะอาดกว่าการใช้ IF ซ้อนกันเป็นลูกโซ่- Guard อาจเป็นค่าเดียว
"A":, ลิสต์1, 2, 3:, หรือช่วง1 TO 5:Branchสุดท้ายสำหรับ "ทุกอย่างอื่น" คือOTHERWISE, ไม่ใช่เงื่อนไขเช่น> 200 - Guards ถูกทดสอบ ตามลำดับ เมื่อมี
1 TO 50:ตามด้วย40 TO 60:ค่า 45 จะเข้า branch แรก ทำให้การกำหนดค่าใน branch ที่สองอาจไม่เกิดขึ้นเลย หาก branch ก่อนหน้าครอบคลุมทุกค่าที่เป็นไปได้OTHERWISEก็จะไม่ทำงานเช่นกัน

CASE จะทำงาน branch แรก whose guard ตรงกับค่า
คำสั่ง CASE สะอาดกว่า IF ที่ซ้อนกันเมื่อคุณกำลัง:
CASE จับคู่ค่าหนึ่งกับความเป็นไปได้หลายอย่าง; IF ที่ซ้อนลึกเกินไปจะอ่านยาก
ข้อใดเป็น guards ที่ถูกต้องใน Cambridge CASE statement? เลือก ทุก ข้อที่เกี่ยวข้อง
ค่าเดียว, รายการค่า, ช่วง และ OTHERWISE การเปรียบเทียบเช่น > 200 ไม่ใช่ guard; สิ่งที่未被ครอบคลุมจะไปที่ Otherwise
ตัวอย่างทำพร้อมกัน : เขียน CASE ใหม่โดยไม่ใช้ CASE
CASE OF MySwitchพร้อม1: ThisChar ← 'a',2: ThisChar ← 'y',3: ThisChar ← '7',OTHERWISE: ThisChar ← '*'- แต่ละค่าจะกลายเป็นหนึ่ง branch ของ chain IF, และ
OTHERWISEจะกลายเป็นELSEสุดท้าย
IF MySwitch = 1 THEN
ThisChar <- 'a'
ELSE
IF MySwitch = 2 THEN
ThisChar <- 'y'
ELSE
IF MySwitch = 3 THEN
ThisChar <- '7'
ELSE
ThisChar <- '*'
ENDIF
ENDIF
ENDIF
- IF สามตัว, ENDIF สามตัว การกลับทางกัน CASE สอง clause ที่กำหนดค่าเดียวกันรวมเป็น guard เดียวที่มีลิสต์ค่า,
1, 2:
ลูปทั้งสาม
- Iteration ทำซ้ำบล็อก, และลูปทั้งสามต่างกันที่ตำแหน่งที่เงื่อนไขถูกทดสอบ
- Count-controlled loop,
FOR i ← 1 TO 10 … NEXT i, รันจำนวนครั้งที่ทราบแล้ว;STEP -1นับถอยหลัง ใช้สำหรับจำนวนคงที่หรือทุก element ของ array - Pre-condition loop,
WHILE … DO … ENDWHILE, ทดสอบ ก่อน ทุกรอบ ดังนั้นอาจรันศูนย์ครั้ง Post-condition loop,REPEAT … UNTIL, ทดสอบ หลัง ทุก รอบ ดังนั้นรันอย่างน้อยหนึ่งครั้งเสมอ

*ตำแหน่งของเงื่อนไขกำหนดว่า body สามารถรันกี่ครั้ง
จับคู่ลูปแต่ละตัวกับเวลาที่คุณจะใช้มัน
FOR = ควบคุมด้วยการนับ; WHILE = เงื่อนไขทดสอบก่อน (0+ รอบ); REPEAT = เงื่อนไขทดสอบหลัง (1+ รอบ)
REPEAT...UNTIL ทดสอบเงื่อนไขของ它以 AFTER body, ดังนั้น body จะรันอย่างน้อยหนึ่งครั้งเสมอ
การทดสอบ post-condition นั้นคือความแตกต่างจาก WHILE ซึ่งสามารถรันศูนย์ครั้งได้
เลือกลูป: คำตอบสองคะแนน
- คะแนนหนึ่งสำหรับ ชื่อ, คะแนนหนึ่งสำหรับ เหตุผล, ในคำของโครงสร้างคะแนน
- Count-controlled, เพราะจำนวนรอบรู้ล่วงหน้าก่อนลูปเริ่ม Post-condition, เพราะ body ต้อง被执行อย่างน้อยหนึ่งครั้ง Pre-condition, เพราะลูปอาจไม่จำเป็นต้อง被执行เลย
- การวนลูปเหนือสี่ elements ของ array ที่เขียนด้วย
WHILEที่มี counter บอกว่า "ไม่ใช่วิธีที่เหมาะสมที่สุด"; FOR loop เหมาะกว่า เพราะทราบจำนวน
คำถามถามให้คุณ "ระบุลูปที่เหมาะสมกว่าและให้เหตุผลในการเลือก" สำหรับ 2 คะแนน สิ่งใดที่จะได้รับคะแนนสอง?
หนึ่งคะแนนสำหรับลูป, หนึ่งสำหรับเหตุผล: จำนวนทราบ, body ต้องรันหนึ่งครั้ง, หรือลูปอาจไม่รันเลย
ตัวอย่างทำพร้อมกัน : ลูปไหนเหมาะกับแต่ละงาน?
- พิมพ์ตารางคูณ 12: จำนวนรู้ล่วงหน้า ดังนั้นใช้ FOR loop
- อ่านตัวเลขต่อไปจนผู้ใช้ใส่ 0: จำนวนไม่รู้และอินพุตแรกอาจเป็น 0 เลย ดังนั้นการทดสอบต้องอยู่เหนือ body: WHILE loop
- ขอรหัสผ่านจนถูกต้อง: ผู้ใช้ต้องถูกถามอย่างน้อยหนึ่งครั้ง ดังนั้นใช้ REPEAT … UNTIL loop
- ถามสองคำถาม: กี่ครั้ง, และ body ต้อง被执行ก่อนการทดสอบครั้งแรกไหม?
"ขอรหัสผ่านซ้ำจนกว่าจะถูก แต่ต้องขออย่างน้อยหนึ่งครั้ง" ลูปใดเหมาะสม?
คุณต้องขออย่างน้อยหนึ่งครั้ง ดังนั้น post-condition REPEAT...UNTIL เป็นตัวเลือกที่เป็นธรรมชาติ
ตารางติดตามค่า
- Trace table บันทึกค่าของตัวแปรทุกตัวขณะคุณ dry run อัลกอริทึมด้วยมือ นี่คือวิธีทดสอบลูปบนกระดาษและเป็นคำถามหกคะแนนใน Paper 2 ส่วนใหญ่
- คอลัมน์ต่อหนึ่งตัวแปร, บวกกับคอลัมน์สำหรับ output ใด ๆ เขียนแถวใหม่เฉพาะเมื่อค่าเปลี่ยน, และประเมินเงื่อนไขลูป ณ วินาทีที่ลูปไปถึงมัน
- ไปต่อจนเงื่อนไขหยุดลูป, แล้วบันทึก output สุดท้าย
ติดตามการวนซ้ำ ท่องผ่านทีละรอบ
ตารางติดตามบันทึกตัวแปรแต่ละตัวหลังจากทุกการท่องของลูป ดูตัวนับ i ขึ้นขณะที่ผลรวมสะสมเพิ่มขึ้น — พอดีกับสิ่งที่คำถามติดตามในข้อสอบให้คุณกรอก
หลังจาก total = 0; FOR i = 1 TO 5: total = total + i, ค่าของ total คืออะไร?
บวก 1+2+3+4+5 = 15 — พอดีกับที่ตารางติดตามสร้างสะสมท่องผ่านทีละรอบ
ตัวอย่างทำพร้อมกัน : ตาราง Trace ที่เติมแล้ว
Count <- 1
Total <- 0
WHILE Total < 10 DO
Total <- Total + Count
Count <- Count + 1
ENDWHILE
OUTPUT Count
- แถวของ (Count, Total): (1, 0) → (2, 1) → (3, 3) → (4, 6) → (5, 10)
- ที่ Total = 10 เงื่อนไข
Total < 10เป็นเท็จ, ลูปจบ, และ output คือ 5 - บรรทัดสุดท้ายเป็นบรรทัดที่ผิดบ่อยที่สุด: ตรวจสอบเงื่อนไขอีกครั้งหนึ่งก่อนเขียนผลลัพธ์
ในการติดตามตัวอย่าง, loop จบลงด้วย Total = 10 และ Count = 5, ดังนั้น output คือ 5
หลังจาก第四次 traverse Total ถึง 10, เงื่อนไข Total < 10 กลายเป็น false, และ Count ได้ถูกเพิ่มเป็น 5
คะแนนที่หลุดหายไป
>=และ>เป็นคำตอบต่างกัน ทดสอบค่าขอบเขตในใจก่อนเขียน ComparisonOTHERWISEเป็น keyword, ไม่ใช่ condition และทุกIF,CASE,WHILEและFORปิดด้วยENDIF,ENDCASE,ENDWHILEหรือNEXT- A
WHILEสามารถรันศูนย์ครั้ง; AREPEATไม่สามารถ เลือกโดยพิจารณาว่า body ต้อง被执行หนึ่งครั้งก่อนการทดสอบครั้งแรกหรือไม่ - ใน trace table, ค่าที่ไม่เปลี่ยนแปลงจะไม่ถูกเขียนทับ, และ output จะถูกเขียนก็ต่อเมื่อบรรทัด
OUTPUTทำงาน
คุณเข้าใจแล้ว
- IF … ELSE … ENDIF สำหรับทางเลือก; nested IFs ปิดแต่ละตัว; CASE สำหรับค่าเดียวเทียบกับหลาย guards, ทดสอบตามลำดับ,
OTHERWISEล่าสุด - FOR จำนวนทราบ · WHILE ทดสอบก่อน, อาจรันศูนย์ครั้ง · REPEAT … UNTIL ทดสอบหลัง, รันอย่างน้อยหนึ่งครั้ง
- อธิบายเหตุผลลูปด้วย ชื่อและเหตุผล: จำนวนทราบ, อาจไม่รัน, ต้องรันหนึ่งครั้ง
- trace table dry-run อัลกอริทึมแถวละหนึ่งต่อการเปลี่ยนแปลง; ตรวจสอบเงื่อนไขอีกครั้งก่อน output สุดท้าย