Transcript while (1)

418115: การเขียนโปรแกรมโครงสร้าง
คาสัง่ while (1)
ประมุข ขันเงิน
[email protected]
yes
 โปรแกรมใน unix (และในระบบปฏิบต
ั กิ ารลูกหลาน เช่น linux และ Mac OS
X) ตัวหนึ่ง
 การทางาน
 พิมพ์ “y” บรรทัดละตัว ไปเรื่อยๆ ไม่ร้ จู บ
 จนกระทั่งมีใครสั่งฆ่า (kill) มัน
 หรือถ้ าส่งข้ อมูลผ่าน pipe ก็จะทาไปเรื่อยๆ จนกระทั่ง pipe พัง (ท่อแตก)
 ประโยชน์
 ใช้ ทดสอบว่าเครื่องคอมพิวเตอร์สามารถรับงานหนักๆ ได้ ไหม
 ใช้ ตอบคาถามของคาสั่งอื่นๆ แทนผู้ใช้
yes
> yes
y
y
y
y
y
y
y
y
คาสัง่ while
 ไวยากรณ์
while (นิพจน์ทางตรรกศาสตร์)
คาสั่ง;
 การทางาน
 เช็คว่านิพจน์ทางตรรกศาสตร์ว่าเป็ นจริงหรือไม่
 ถ้ าเป็ นจริงให้ ทาคาสั่งที่อยู่ใต้ คาสั่ง while
 หลังจากนั้นกลับไปเช็คใหม่
 กล่าวคือทางานไปเรื่อยๆ จนกว่าเงื่อนไขจะเป็ นเท็จ
เขียน yes
 ต้ องการให้ มน
ั วนไปเรื่อยๆ ไม่ร้ จู บ
 ฉะนั้นเงื่อนไขที่ใส่ต้องเป็ นจริงเสมอ
 อะไรจริงเสมอ?  อะไรก็ตามที่ไม่ใช่ 0
#include <stdio.h>
int main()
{
while (1)
printf("y\n");
return 0;
}
while และ Compound Statement
 ถ้ าต้ องการให้ การวนรอบแต่ละรอบมีการทาคาสั่งมากกว่าหนึ่งคาสั่ง
ให้ ใช้ compound statement แทน “คาสั่ง;”
#include <stdio.h>
int main()
{
while (1)
{
printf("y");
printf("\n");
}
return 0;
}
คาสัง่ do
 ไวยากรณ์
do {
คาสั่ง 1;
คาสั่ง 2;
คาสั่ง 3;
:
} while (เงื่อนไข);
คาสัง่ do
 การทางาน
 ทาคาสั่งใน compound statement ทั้งหมด
 แล้ วไปเช็คเงื่อนไขที่อยู่ข้างล่าง
 ถ้ าเงื่อนไขเป็ นจริงให้ ย้อนไปทาคาสั่งใน compound statement ใหม่
 ทางานไปเรื่อยๆ จนกว่าเงื่อนไขจะเป็ นเท็จ
 ข้ อแตกต่างกับคาสั่ง while
 คาสั่ง while เช็คก่อนทา
 คาสั่ง do ทาก่อนเช็ค
เขียน yes ด้วยคาสัง่ do
#include <stdio.h>
int main()
{
do
{
printf("y");
printf("\n");
} while (1);
return 0;
}
โปรแกรมหาค่าเฉลีย่ ของชุดตัวเลข
 ต้ องการโปรแกรมสาหรับอ่านตัวเลขชุดหนึ่งมาจากผู้ใช้
 อ่านเลขเข้ ามาทีละตัว
 หลังจากอ่านให้ ถามว่าต้ องการป้ อนข้ อมูลต่อหรือไม่
 ถ้ าใช้ กใ็ ห้ อ่านเข้ ามาใหม่
 ถ้ าไม่ใช่กใ็ ห้ หยุดอ่าน
 หลังจากนั้นบอกผู้ใช้ ว่าป้ อนตัวเลขเข้ ามากี่ตวั แล้ ว
 แล้ วหาค่าเฉลี่ยของเลขเหล่านั้น
ตัวอย่างผลลัพธ์
Enter a number: 10
Do you want to continue? (1=yes, 0=no): 1
Enter a number: 20
Do you want to continue? (1=yes, 0=no): 1
Enter a number: 60
Do you want to continue? (1=yes, 0=no): 0
You entered 3 number(s).
The mean is 30.000000.
ตัวอย่างผลลัพธ์
Enter a number: 441.93
Do you want to continue?
Enter a number: 841
Do you want to continue?
Enter a number: 7.65
Do you want to continue?
Enter a number: 28.28
Do you want to continue?
Enter a number: -46.49
Do you want to continue?
You entered 5 number(s).
The mean is 322.062200.
(1=yes, 0=no): 1
(1=yes, 0=no): 1
(1=yes, 0=no): 1
(1=yes, 0=no): 1
(1=yes, 0=no): 0
ออกแบบโปรแกรม
 การหาค่าเฉลี่ย
 ต้ องหาผลบวกของจานวนที่ผ้ ูใช้ ให้ มาทั้งหมด
 ต้ องนับจานวนของเลขที่ผ้ ูใช้ ให้ มาทั้งหมด
 เสร็จแล้ วเอาผลบวกหารด้ วยจานวน
 ตัวแปร
 double sum; สาหรับเก็บผลบวก
 int count; สาหรับเก็บจานวน
 ในลูปแต่ละรอบ
 อ่านข้ อมูลเข้ าเก็บใส่ตัวแปร สมมติเป็ น x
 sum += x;
 count++;
ออกแบบโปรแกรม
 หลังจากอ่านเลขจากผู้ใช้ ให้ ถามผู้ใช้ ว่าต้ องการต่อหรือไม่
 สมมติว่าเราอ่านข้ อมูลมาเก็บไว้ ในตัวแปร choice
 เราจะให้ ลูปทางานต่อไปก็ต่อเมื่อ choice == 1
ลูป
do
{
double x;
printf("Enter a number: ");
scanf("%lf", &x);
sum += x;
count++;
printf("Do you want to continue? (1=yes, 0=no): ");
scanf("%d", &choice);
} while (choice == 1);
ทัง้ โปรแกรม
#include <stdio.h>
int main()
{
double sum = 0;
int count = 0;
int choice;
[ลูปของหน้าที่แล้ว]
printf("You entered %d number(s).\n", count);
printf("The mean is %lf.\n", sum / count);
return 0;
}
โปรแกรมพิมพ์ 0 ถึง n-1
 ให้ ผ้ ใู ช้ ป้อนจานวนเต็ม n
 โปรแกรมพิมพ์เลข 0 ถึง n-1 ทีละตัว
ตัวอย่างผลลัพธ์
Enter n: 5
0
1
2
3
4
ตัวอย่างผลลัพธ์
Enter n: 10
0
1
2
3
4
5
6
7
8
9
ตัวแปร counter
 ในการเขียนลูปที่มจี านวนครั้งการวนรอบคงที่
เรามักจะมีตวั แปรตัวหนึ่งบอกว่าลูปทางานไปกี่ครั้งแล้ ว
 ตัวแปรพวกนี้มกั จะเรียกว่าตัวแปร counter
 ตัวแปร counter จะมีค่าเพิ่มขึ้นหนึ่ง ทุกครั้งที่ loop ทางาน
 Loop จะหยุดทางานเมื่อตัวแปร counter มีค่าเท่ากับจานวนครั้งที่เราต้ องการ
ลูป
 ในกรณีน้ เี ราจะมีตวั แปร counter ตัวหนึ่งชื่อ i
 ตอนแรก i มีค่าเท่ากับ 0
 ในแต่ละลูป
 พิมพ์ i
 เพิ่มค่า i
 ลูปจะจบการทางานก็ต่อเมื่อ i มีค่าเท่ากับ n
 กล่าวคือมันจะทางานไปเรื่อยๆ ตราบที่ i < n
ลูป
int i = 0;
while (i < n)
{
printf("%d\n", i);
i++;
}
ทัง้ โปรแกรม
#include <stdio.h>
int main()
{
int n;
printf("Enter n: ");
scanf("%d", &n);
int i = 0;
while (i < n)
{
printf("%d\n", i);
i++;
}
return 0;
}
แพทเทิร์น
 สมมติว่าเราต้ องการทาอะไรซา้ ๆ กัน n ครั้ง
 สร้ างตัวแปร counter สมมติว่าให้ ช่ ือ i
 ตอนแรกให้ i มีค่าเท่ากับ 0
 สร้ าง loop while โดยเช็คว่า i < n
 ในลูปให้ ทาสิ่งที่คุณต้ องการ
 เสร็จแล้ วสั่ง i++
แพทเทิร์น
int i = 0;
while (i < n)
{
[ทาสิง่ ที่ตอ้ งการทาซ้ า n ครั้ง]
i++;
}
โปรแกรมพิมพ์สเี่ หลีย่ ม
 ผู้ใช้ กาหนดความยาวด้ านของสี่เหลี่ยม: n
 พิมพ์ตารางขนาด n คูณ n ที่ประกอบด้ วยตัวอักษรดอกจัน (*)
Enter n: 5
*****
*****
*****
*****
*****
ตัวอย่างผลลัพธ์
Enter n: 9
*********
*********
*********
*********
*********
*********
*********
*********
*********
ลูปซ้อนลูป
 เราต้ องการ:
 ทาซา้ n รอบ โดยแต่ละรอบ
 ต้ องพิมพ์เครื่องหมายดอกจัน n รอบ
 แล้ วพิมพ์ \n
ใช้แพทเทิร์น
int i = 0;
while (i < n)
{
[พิมพ์ดอกจัน n ดอก]
printf("\n");
i++;
}
ใช้แพทเทิร์น
int i = 0;
while (i < n)
{
int j = 0;
while (j < n)
{
[พิมพ์ดอกจัน 1 ดอก]
j++;
}
printf("\n");
i++;
}
ใช้แพทเทิร์น
int i = 0;
while (i < n)
{
int j = 0;
while (j < n)
{
printf("*");
j++;
}
printf("\n");
i++;
}
ทัง้ โปรแกรม
#include <stdio.h>
int main()
{
int n;
printf("Enter n: ");
scanf("%d", &n);
int i = 0;
while (i < n) {
int j = 0;
while (j < n) {
printf("*");
j++;
}
printf("\n");
i++;
}
return 0;
}
โปรแกรมพิมพ์สามเหลีย่ ม
 คราวนี้เอาแบบนี้บ้าง
Enter n: 5
*
**
***
****
*****
ตัวอย่างผลลัพธ์
Enter n: 8
*
**
***
****
*****
******
*******
********
ออกแบบโปรแกรม
 ทาซา้ n ครั้งเหมือนเดิม
 แต่ในการทาซา้ แต่ละครั้งต้ องพิมพ์จานวนดอกจันไม่เหมือนกัน
 ครั้งที่ 1 พิมพ์ 1 ดวง
 ครั้งที่ 2 พิมพ์ 2 ดวง
 ครั้งที่ 3 พิมพ์ 3 ดวง
 เราจะรู้ได้ อย่างไรว่าตอนนี้เราอยู่ในการวนซา้ ครั้งที่เท่าใด?
 ดูตัวแปร counter!
ลูปโปรแกรมพิมพ์สเี่ หลีย่ ม
int i = 0;
while (i < n)
{
[พิมพ์ดอกจัน n ดอก]
printf("\n");
i++;
}
 สังเกตว่า i+1 คือจานวนครั้งที่เราทาซา้ มาแล้ ว
ลูปโปรแกรมพิมพ์สเี่ หลีย่ ม
int i = 0;
while (i < n)
{
[พิมพ์ดอกจัน i+1 ดอก]
printf("\n");
i++;
}
ลูปโปรแกรมพิมพ์สเี่ หลีย่ ม
int i = 0;
while (i < n)
{
int j = 0;
while (j < i+1)
{
printf("*");
j++;
}
printf("\n");
i++;
}
ทัง้ โปรแกรม
#include <stdio.h>
int main()
{
int n;
printf("Enter n: ");
scanf("%d", &n);
int i = 0;
while (i < n) {
int j = 0;
while (j < i+1) {
printf("*");
j++;
}
printf("\n");
i++;
}
return 0;
}
โปรแกรมพิมพ์สามเหลีย่ มอีกแบบ
 คราวนี้เอาแบบนี้บ้าง
Enter n: 5
*
**
***
****
*****
ตัวอย่างผลลัพธ์
Enter n: 9
*
**
***
****
*****
******
*******
********
*********
ออกแบบโปรแกรม
 ทาซา้ n รอบเหมือนเดิม
 ในการทาซา้ รอบที่ i เราต้ อง
 พิมพ์ดอกจัน i+1 ดอก (เหมือนกับโปรแกรมพิมพ์สามเหลี่ยม)
 แต่ก่อนหน้ าที่จะพิมพ์ดอกจันต้ องพิมพ์ space ให้ ดอกจันชิดขวา
 เราต้ องพิมพ์ space กี่ตวั ?
 ความจริงเราสร้ างตารางขนาด n x n
 แต่ละแถวมีตัวอักษร n ตัวพอดี
 ฉะนั้นเมื่อมีดอกจัน i+1 ตัว เราต้ องมี space ทั้งหมด n-1 ตัว
ลูป
int i = 0;
while (i < n)
{
[พิมพ์ space n-i-1 ตัว]
[พิมพ์ดอกจัน i+1 ดอก]
printf("\n");
i++;
}
ลูป
int i = 0;
while (i < n)
{
int j = 0;
while (j < n-i-1) {
printf(" ");
j++;
}
j = 0;
while (j < i+1) {
printf("*");
j++;
}
printf("\n");
i++;
}
โปรแกรมพิมพ์ปิระมิด
 จาปิ ระมิดในแล็ปแรกได้ ไหม?
Enter n: 5
*
* *
* * *
* * * *
* * * * *
ตัวอย่างผลลัพธ์
Enter n: 8
*
* *
* * *
* * * *
* * * * *
* * * * * *
* * * * * * *
* * * * * * * *
สังเกต
 ทุกบรรทัดจบด้ วยดอกจันหนึ่งตัว
 ถ้ าเรานับข้ อความ “* “ (ดอกจันตามด้ วย space) เป็ นตัวอักษรหนึ่งตัว
เราพบว่าทุกบรรทัดจะมีตวั อักษรที่ไม่ใช่ดอกจันตัวสุดท้ ายเท่ากับ n-1 ตัวพอดี
สังเกต
 กล่าวคือ
 ในบรรทัดที่ 1 (i = 0)
 มี space n-1 ตัว
 ตามด้ วย “* “ 0 ตัว
 ตามด้ วยดอกจัน 1 ตัว
 ในบรรทัดที่ 2 (i = 1)
 มี space n-2 ตัว
 ตามด้ วย “* “ 1 ตัว
 ตามด้ วยดอกจัน 1 ตัว
 ในบรรทัดที่ 3 (i = 2)
 มี space n-3 ตัว
 ตามด้ วย “* “ 2 ตัว
 ตามด้ วยดอกจัน 1 ตัว
สังเกต
 ฉะนั้น
 ในบรรทัดที่ i+1
 มี space n-i-1 ตัว
 ตามด้ วย “* “ i ตัว
 ตามด้ วยดอกจัน 1 ตัว
ลูป
int i = 0;
while (i < n)
{
[พิมพ์ space n-i-1 ตัว]
[พิมพ์ขอ้ ความ “* “ i ครั้ง]
printf(“*");
printf("\n");
i++;
}
ลูป
int i = 0;
while (i < n)
{
int j = 0;
while (j < n-i-1) {
printf(" ");
j++;
}
j = 0;
while (j < i) {
printf("* ");
j++;
}
printf("*");
printf("\n");
i++;
}
โปรแกรมพิมพ์กรอบซ้อนกรอบ
Enter n: 1
*
Enter n: 2
*****
*
*
* * *
*
*
*****
ตัวอย่างผลลัพธ์
Enter n: 3
*********
*
*
* ***** *
* *
* *
* * * * *
* *
* *
* ***** *
*
*
*********
ตัวอย่างผลลัพธ์
Enter n: 4
*************
*
*
* ********* *
* *
* *
* * ***** * *
* * *
* * *
* * * * * * *
* * *
* * *
* * ***** * *
* *
* *
* ********* *
*
*
*************
สังเกต
 กรอบสี่เหลี่ยมที่ใหญ่ท่สี ดุ กว้ างเท่าไหร่ ?
 ตอบ: 4*n-3
 กล่าวคือเราต้ องสร้ างตารางขนาด 4*n-3 คูณ 4*n-3
 แต่ละช่องของตารางจะเป็ นดอกจัน (*) หรือไม่กเ็ ป็ น space
ระบบพิกดั
 แล้ วช่องช่องหนึ่งจะเป็ นดอกจันเมื่อไหร่ ?
 ก่อนอื่นเราลองสร้ างระบบพิกดั บนตารางนี้เสียก่อน
|012345678
-+--------0|*********
1|*@@@@@@@*
2|*@*****@*
3|*@*@@@*@*
4|*@*@*@*@*
5|*@*@@@*@*
6|*@*****@*
7|*@@@@@@@*
8|*********
ระบบพิกดั
 ช่อง (0,0)
|012345678
-+--------0|*********
1|*@@@@@@@*
2|*@*****@*
3|*@*@@@*@*
4|*@*@*@*@*
5|*@*@@@*@*
6|*@*****@*
7|*@@@@@@@*
8|*********
ระบบพิกดั
 ช่อง (1,0)
|012345678
-+--------0|*********
1|*@@@@@@@*
2|*@*****@*
3|*@*@@@*@*
4|*@*@*@*@*
5|*@*@@@*@*
6|*@*****@*
7|*@@@@@@@*
8|*********
ระบบพิกดั
 ช่อง (1,1)
|012345678
-+--------0|*********
1|*@@@@@@@*
2|*@*****@*
3|*@*@@@*@*
4|*@*@*@*@*
5|*@*@@@*@*
6|*@*****@*
7|*@@@@@@@*
8|*********
ระบบพิกดั
 ช่อง (6,7)
|012345678
-+--------0|*********
1|*@@@@@@@*
2|*@*****@*
3|*@*@@@*@*
4|*@*@*@*@*
5|*@*@@@*@*
6|*@*****@*
7|*@@@@@@@*
8|*********
สังเกต
 ช่องตรงกลางชื่อช่องใด?
 ตอบ: (2*n-2, 2*n-2)
 ช่องช่องหนึ่งจะเป็ นดอกจันเมื่อใด?
 เมื่อมันอยู่ใน “วง” ที่ห่างออกจากจุดศูนย์กลางเป็ นระยะทางเป็ นเลขคู่
วงระยะ 0
|012345678
-+--------0|*********
1|*@@@@@@@*
2|*@*****@*
3|*@*@@@*@*
4|*@*@*@*@*
5|*@*@@@*@*
6|*@*****@*
7|*@@@@@@@*
8|*********
วงระยะ 1
|012345678
-+--------0|*********
1|*@@@@@@@*
2|*@*****@*
3|*@*@@@*@*
4|*@*@*@*@*
5|*@*@@@*@*
6|*@*****@*
7|*@@@@@@@*
8|*********
วงระยะ 2
|012345678
-+--------0|*********
1|*@@@@@@@*
2|*@*****@*
3|*@*@@@*@*
4|*@*@*@*@*
5|*@*@@@*@*
6|*@*****@*
7|*@@@@@@@*
8|*********
วงระยะ 3
|012345678
-+--------0|*********
1|*@@@@@@@*
2|*@*****@*
3|*@*@@@*@*
4|*@*@*@*@*
5|*@*@@@*@*
6|*@*****@*
7|*@@@@@@@*
8|*********
ช่องวงระยะ 1
 มี 8 ช่องด้ วยกัน
 (2*n-3, 2*n-3)
 (2*n-2, 2*n-3)
 (2*n-1, 2*n-3)
 (2*n-3, 2*n-2)
 (2*n-1, 2*n-2)
 (2*n-3, 2*n-1)
 (2*n-2, 2*n-1)
 (2*n-1, 2*n-1)
ช่องวงระยะ 1
 เอา (2*n-2, 2*n-2) ไปลบออกจากทุกช่อง
 (2*n-3, 2*n-3) - (2*n-2, 2*n-2) = (-1, -1)
 (2*n-2, 2*n-3) - (2*n-2, 2*n-2) = (0, -1)
 (2*n-1, 2*n-3) - (2*n-2, 2*n-2) = (1, -1)
 (2*n-3, 2*n-2) - (2*n-2, 2*n-2) = (-1, 0)
 (2*n-1, 2*n-2) - (2*n-2, 2*n-2) = (1, 0)
 (2*n-3, 2*n-1) - (2*n-2, 2*n-2) = (-1, 1)
 (2*n-2, 2*n-1) - (2*n-2, 2*n-2) = (0, 1)
 (2*n-1, 2*n-1) - (2*n-2, 2*n-2) = (1, 1)
 สังเกตว่า
 ถ้ าหาค่าสัมบูรณ์ของค่า x และ y จะได้ ว่าตัวที่มากกว่าจะมีค่าเป็ น 1
ช่องแต่ละช่องอยู่วงไหน?
 สมมติว่าเราสนใจช่อง (j,i)
 เราจะหา “ระยะ” ของวงที่ช่อง (j,i) อยู่ได้ อย่างไร?
 จากหน้ าที่แล้ วสามารถสรุปเป็ นกฎได้ ว่า
 “ช่อง (j,i) จะอยู่ในวง max( abs(i – (2*n-2)), abs(j – (2*n-2)) )”
ลูป
int i = 0;
while (i < 4*n-3)
{
[พิมพ์ตวั อักษร 4*n-3 ตัว]
printf("\n");
i++;
}
ลูป
while (i < 4*n-3)
{
int j = 0;
while (j < 4*n-3)
{
[พิมพ์ตวั อักษร 1 ตัว]
j++;
}
printf("\n");
i++;
}
ลูป
while (i < 4*n-3)
{
int j = 0;
while (j < 4*n-3)
{
[คานวณ d = ระยะของวงของช่อง (j,i) ]
if (d % 2 == 0)
printf("*");
else
printf(" ");
j++;
}
printf("\n");
i++;
}
ลูป
while (i < 4*n-3)
{
int j = 0;
while (j < 4*n-3)
{
int dx = abs(j - (2*n-2));
int dy = abs(i - (2*n-2));
int d = (dx > dy) ? dx : dy;
if (d % 2 == 0)
printf("*");
else
printf(" ");
j++;
}
printf("\n");
i++;
}
ทัง้ โปรแกรม
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
printf("Enter n: ");
scanf("%d", &n);
int i = 0;
while (i < 4*n-3) {
int j = 0;
while (j < 4*n-3) {
int dx = abs(j - (2*n-2));
int dy = abs(i - (2*n-2));
int d = (dx > dy) ? dx : dy;
if (d % 2 == 0)
printf("*");
else
printf(" ");
j++;
}
printf("\n");
i++;
}
return 0;
}