C การวนซ้ำ
while
#include <stdio.h>
int main(void)
{
int count = 3;
while (count > 0) {
printf("นับถอยหลัง: %d\n", count);
count--;
}
printf("จบ\n");
return 0;
}เช็คเงื่อนไข ก่อน วนแต่ละรอบ — ถ้าเงื่อนไขเท็จตั้งแต่แรก body ไม่ทำงานเลย
do-while
int n = 0;
int ok;
do {
printf("ใส่เลข 1-10: ");
ok = scanf("%d", &n);
if (ok != 1) { // ผู้ใช้พิมพ์ไม่ใช่ตัวเลข
int c;
while ((c = getchar()) != '\n' && c != EOF) { } // ทิ้ง token ที่ผิด
n = 0; // ให้เงื่อนไขวนต่อ
if (c == EOF) break; // stdin ปิดแล้ว — เลิกวน
}
} while (ok != 1 || n < 1 || n > 10);เช็คเงื่อนไข หลัง วน — body ทำงานอย่างน้อย 1 รอบเสมอ เหมาะกับการรับ input จนกว่าจะถูกต้อง
scanf("%d")ที่ไม่เช็คค่าคืน: ถ้าผู้ใช้พิมพ์ตัวอักษรscanfจะคืน 0 ทิ้ง token ผิดไว้ใน buffer แล้ววนอ่านตัวเดิมซ้ำไม่จบ — ต้องเช็คค่าคืนและล้าง buffer
for
for (int i = 0; i < 5; i++) {
printf("%d ", i); // 0 1 2 3 4
}
printf("\n");3 ส่วน: เริ่มต้น; เงื่อนไขวนต่อ; ทำท้ายรอบ
- ประกาศตัวนับใน
forได้ตั้งแต่ C99 (for (int i = ...)) —iมีชีวิตแค่ในลูป ใช้เสมอ - ถ้าต้องคอมไพล์ด้วย
-std=c89ต้องประกาศiก่อนลูป
for (int i = 10; i > 0; i -= 2) {
printf("%d ", i); // 10 8 6 4 2
}วนอาร์เรย์ — ระวังขอบเขต
int nums[5] = {10, 20, 30, 40, 50};
for (int i = 0; i < 5; i++) { // i จาก 0 ถึง 4
printf("%d\n", nums[i]);
}อาร์เรย์ 5 ตัว มี index 0 ถึง 4 — เงื่อนไขต้องเป็น i < 5 ไม่ใช่ i <= 5
for (int i = 0; i <= 5; i++) { // ❌ i = 5 เข้าถึง nums[5] ซึ่งไม่มี!
printf("%d\n", nums[i]); // undefined behavior — อ่านนอกขอบเขต
}C ไม่ตรวจขอบเขตอาร์เรย์ — nums[5], nums[100], nums[-1] คอมไพล์ผ่านและรัน อาจได้ค่าขยะ อาจ crash อาจเขียนทับตัวแปรอื่น นี่คือ off-by-one error ที่พบบ่อยที่สุดใน C
หลีกเลี่ยงการ hardcode ขนาด:
size_t len = sizeof(nums) / sizeof(nums[0]); // = 5
for (size_t i = 0; i < len; i++) {
printf("%d\n", nums[i]);
}(เทคนิคนี้ใช้ได้เฉพาะกับอาร์เรย์จริง ไม่ใช่ pointer — บทที่ 9, 12)
break และ continue
for (int i = 1; i <= 10; i++) {
if (i % 2 != 0) {
continue; // ข้ามเลขคี่ ไปรอบถัดไป
}
if (i > 6) {
break; // เจอเกิน 6 ออกจากลูปเลย
}
printf("%d ", i); // 2 4 6
}
printf("\n");break— ออกจากลูปชั้นในสุดทันทีcontinue— ข้ามส่วนที่เหลือของ body ไปเช็คเงื่อนไขรอบถัดไป (ในforยังทำส่วนi++ก่อน)
C ไม่มี break 2; แบบ PHP — ออกจากลูปซ้อนใช้ flag หรือ goto:
int found = 0;
for (int i = 0; i < rows && !found; i++) {
for (int j = 0; j < cols; j++) {
if (grid[i][j] == target) {
found = 1;
break;
}
}
}หรือ goto (กรณีนี้ยอมรับได้):
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (grid[i][j] == target) goto done;
}
}
done:
printf("เสร็จ\n");infinite loop
while (1) {
// ... ต้องมี break ข้างในไม่งั้นไม่จบ
if (should_stop()) break;
}
for (;;) { // เขียนแบบนี้ก็ได้ ("forever")
// ...
}ลูปซ้อน — ตารางสูตรคูณ
for (int i = 1; i <= 5; i++) {
for (int j = 1; j <= 5; j++) {
printf("%3d", i * j);
}
printf("\n");
} 1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
4 8 12 16 20
5 10 15 20 25เรื่องที่คนมักพลาด
i <= nแทนi < nเมื่อวนอาร์เรย์ขนาดn— เข้าถึง index ที่ไม่มี (off-by-one, UB)- ลืมเพิ่มตัวนับ —
while (i < 10) { printf(...); }ไม่มีi++= infinite loop for (unsigned i = n; i >= 0; i--)—unsignedไม่มีทาง< 0วนไม่จบ ใช้intหรือวนขึ้น- แก้ตัวนับข้างใน body ของ
forจนงงว่าวนกี่รอบ — ถ้าต้องทำ ใช้whileให้ชัด ;หลังfor(...)โดยไม่ตั้งใจ —for (i=0; i<5; i++);body ว่าง โค้ดข้างล่างทำครั้งเดียว-Wallเตือน (-Wempty-body)- ประกาศ
int iในforแล้วใช้iหลังลูป — scope จบที่ลูป (C99+) ต้องประกาศก่อนลูปถ้าต้องใช้ต่อ do { scanf("%d", &n); } while (...)ไม่เช็คค่าคืน — ผู้ใช้พิมพ์ตัวอักษร →scanfคืน 0 ไม่กิน token ผิด → วนอ่านตัวเดิมไม่จบ เช็คค่าคืน + ล้าง buffer + จับ EOF
สรุป
whileเช็คก่อน,do-whileเช็คหลัง (ทำอย่างน้อย 1 รอบ),forเมื่อมีตัวนับ- ประกาศตัวนับใน
for(for (int i = 0; ...)) — C99 ขึ้นไป - วนอาร์เรย์ขนาด
n:i < n(ไม่ใช่<=) — C ไม่ตรวจขอบเขตให้ breakออกลูปชั้นในสุด,continueข้ามไปรอบถัดไป; ลูปซ้อนใช้ flag หรือgoto- เลี่ยง
unsignedเป็นตัวนับที่ต้องเทียบ>= 0
บทถัดไปว่าด้วยฟังก์ชัน — prototype, pass by value, recursion และเหตุผลที่ต้องประกาศก่อนใช้