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;
}