ABC_03_SP_CH04

Download Report

Transcript ABC_03_SP_CH04

Chapter 4. 제어의 흐름
4.1 관계, 등가, 논리연산자
- 관계 연산자 : < > <= >=
- 등가 연산자 : == !=
- 논리 연산자 : ! && ||
! : 단항 연산자, ! 이외에는 모두 이항 연산자.
논리연산자는 연산 후 정수값 0 또는 1을 생성.
0, 0.0, NULL, '0' : 거짓(false)
기타 : 참(true)
1
4.2 관계 연산자와 수식
(예)
a > 3
a < b
-1.3 >= (2.0 * x + 3.3)
a<b<c
/* 구문은 올바르나 혼동의 위험 */
(주의)
3 < 7 < 5 : 참(true) - false를 예측
∵ (3 < 7) < 5
1
< 5
∴ 참(true)
3 < 1 < 5도 true임 (3<1 == 0, 0<5 == 1, ∴ true)
2
선언 및 초기화
char
int
double
c = 'w';
i = 1, j = 2, k = -7;
x = 7e+33, y = 0.001;
수식
동일한 수식
결과 값
'a' + 1 < c
('a' + 1) < c
1
- i - 5 * j >= k + 1
((- i) - (5 * j)) >= (k + 1)
0
3<j<5
(3 < j) < 5
1
x - 3.333 <= x + y
(x - 3.333) <= (x + y)
1
x<x+y
x < (x + y)
0
x가 매우 큰 수이고 y는 아주 작은 경우 y는 0.0으로 표현되
며 (x+y)의 값은 x값과 같은 값으로 표현되는 경우가 있음.3
4.3 등가연산자
(예)
c == 'A'
k !=
-2
x + y == 3 * z -7
(주의)
if (a == 1)
....
v.s.
if(a = 1)
....
4
4.4 논리연산자와 수식
(예)
!a
!(x + 7.7)
!(a < b || c < d)
(주의) !!x != x
선언 및 초기화
char c = 'A'; int i = 7, j = 7; double x = 0.0, y = 2.3;
수식
동일 수식
결과값
!c
!c
0
! (i - j)
! (i - j)
1
!i-j
! ! (x + y)
!x*!!y
(! i) - j
! (! (x + y))
(! x) * (! (! y))
-7
1
1
5
(예)
a && b
a || b
3 && (-2 * a + 7)
선언 및 초기화
char c = 'B'; int i = 3, j = 3, k = 3; double x = 0.0, y = 2.3;
수식
동일 수식
결과값
i && j && k
(i && j) && k
1
x || i && j - 3
x || (i && (j - 3))
0
i < j && x < y
(i < j) && (x < y)
0
i < j || x < y
(i < j) && (x < y)
1
'A' <= c && c <= 'Z'
('A' <= c) && (c <= 'Z')
1
c - 1 == 'A' || c + 1 == 'Z'
((c - 1) == 'A') || ((c + 1) == 'Z')
1
6
4.5 복합문
(예)
{
a += b += c;
/* a = a + (b = (b +c)) */
printf(....);
}
{
int a, b, c;
a = 1;
{
b = 2;
c = 3;
}
}
7
4.6 수식과 공백문장
a = b;
a = b + c;
;
printf("\n");;
if (a < b && !(c < d));
/* if ((a >= b) || (c < d)) */
else
/*
i++;
*/
i++;
8
4.7 if와 if-else문
- if 문
if ( expr )
statement
- 복합문의 사용
if ( j < k )
min = j;
if ( j < k )
printf("j is smaller than k");
if ( j < k ) {
/* 두개의 if문을 하나로 */
min = j;
printf("j is smaller than k");
}
9
- if-else 문
if ( expr )
statement1
else
ststement2
(예) if ( x < y )
min = x;
else
min = y;
10
if ( c >= 'a' && c <= 'z' )
lower_case_count ++;
else
{
other_count ++;
printf("%c is not a lower case letter\n", c);
}
(주의)
if ( i != j ) {
i ++;
j ++;
};
/* if 문의 끝 */
else
i = i - j;
/* ERROR */
11
if ( a == 1 )
if ( b== 2 )
printf("***\n");
/* if (( a == 1 ) && ( b == 2 )) */
if ( a == 1 )
if ( b == 2 )
printf("***\n");
else
printf("###\n");
(주의)
if ( a == 1)
if ( b == 2 )
printf("***\n");
else
printf("###\n");
12
숙제
1. 3개의 정수 YYYY, MM, DD를 입력하여,
그것이 YYYY년 MM월 DD일이라 간주하고
그날의 요일을 알아내는 program을 작성하라.
단, ⅰ) data의 범위가 정당한지 check하여 만일 잘못 입력
되었으면 message 및 prompt를 출력한 후 재 입력
할 것. (예, 4004 9 47)
ⅱ) 서기 1년 1월 1일은 월요일이라 가정한다.
ⅲ) 윤년 / 평년 (leap / ordinary year)
if ( YYYY % 4 == 0 ) 윤년
if ( YYYY % 100 == 0) 평년
if ( YYYY % 400 == 0) 윤년
2. 3개의 정수를 입력하여 삼각형의 각 변의 길이라 간주하고,
13
어떤 삼각형인가를 알아내는 program을 작성하라.
4.8 while문
while ( expr )
statement
(예)
while ( i ++ < n )
factorial *= i;
/* factorial */
while ( (c = getchar( )) != EOF ) {
if ( c >= 'a' && c <= 'z' )
++ lowercase_count;
++ total_count;
}
14
(주의)
while ( -- n )
......
/* n이 음수이면 infinite loop */
while ( --n > 0)
......
/* n이 음수이어도 문제 없음 */
- 공백문장의 사용
while ( (c = getchar( )) == ' ')
;
/* programmer의 의도가 분명함 */
while ( (c = getchar( )) == ' ') ;
/* 실수일 가능성 있음 */
15
숙제
3. -9999가 나올 때까지 계속 정수를 입력하여,
최대치(max), 최소치(min), 합(sum)과 평균(average)을
구하는 program을 작성하라.
단, -9999는 계산에서 제외할 것.
4. Gettysburg Address에 사용된 대문자, 소문자 및 그 외의
글자수를 count하는 program을 작성하라.
16
숙제
5. YYYY MM을 입력하여 그 달의 달력을 출력하는 program을
작성하라. (공휴일 표시 무시)
(예)
2003년 3월
일 월
화
수
목
금
토
1
8
2
3
4
5
6
7
......
23 24 25 26 27 28 29
30 31
17
숙제
6. 홀 • 짝 program.
컴퓨터와 end-user가 각기 100원씩 가지고 홀 • 짝 game을
하여 누군가가 돈을 다 잃으면 끝이남. 누군가가 이기거나
질때까지의 횟수와 승자를 표시하는 program을 작성하라.
단 1회 betting은 1∼ 20원으로 제한.
7. 가위 • 바위 • 보 program: 누군가가 이길때 까지 가위 • 바위
• 보 game을 수행하는 program을 작성하라.
ⅰ) 2명 (computer v.s. end-user)
ⅱ) 3명 (2 computers v.s. end-user)
ⅲ) (BONUS + 5%)
5명 (4 computers v.s. end-user)
18
4.9 for문
for ( expr1 ; expr2 ; expr3 )
statement
next statement
- 같은 연산을 수행하는 while문.
expr1 ;
while ( expr2 ) {
statement
expr3 ;
}
next statement
19
(예)
for ( i = 1; i <= n; ++i )
factorial *= i;
/* factorial */
for ( j = 2; k % j == 0; ++j ) { /* k의 약수와 그 합 */
printf("%d is a divisor of %d\n", j, k);
sum += j;
}
20
- for문에서 expression의 생략.
i = 1;
sum = 0;
for ( ; i <= 10; ++ i )
sum = sum + i;
i = 1;
sum = 0;
for ( ; i <= 10; )
sum += i ++;
for ( ; ; )
......
/* 무한루프 */
21
- nested for문.
for ( ...... )
for ( ...... )
for ( ...... )
statement
(예)
for (i=1; i<=10; ++i) {
for (j=1; j<=10; ++j)
printf ("%5d", i+j);
printf ("\n");
}
22
실행결과
i j
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
12
3
4
5
6
7
8
9
10
11
12
13
4
5
6
7
8
9
10
11
12
13
14
5
6
7
8
9
10
11
12
13
14
15
6
7
8
9
10
11
12
13
14
15
16
7
8
9
10
11
12
13
14
15
16
17
8
9
10
11
12
13
14
15
16
17
18
9
10
11
12
13
14
15
16
17
18
19
10
11
12
13
14
15
16
17
18
19
23
20
숙제
8. nested for문을 이용하여 구구단표를 작성하라.
1
2
3
4
5
6
7
8
9
-----------------------------------------1
1
2
3
4
5
6
7
8
9
2
2
4
6
8
10
12
14
16
18
3
3
6
9
12
15
18
21
24
27
4
4
8
12
16
20
24
28
32
36
5
5
……….
24
4.10 부울 변수 - 생략
4.11 comma 연산자
- 우선순위가 가장 낮음.
comma_expression ::= expr, expr
(예)
a = 0, b = 1 /* 문장이 아니라 comma expression 임 */
for ( sum = 0, i = 1; i <= n; ++i )
sum += i;
for ( sum = 0, i = 1; i <= n; sum += i, ++i )
;
25
4.12 do문
do_statement ::= do statement while (expr);
do
statement
while ( expr ) ;
next statement
26
(예) 0이 입력될때까지 입력된 정수의 합을 구하기.
i = 0;
sum = 0;
do {
sum = sum + i;
scanf("%d", &i);
/* prompt 생략 */
} while ( i > 0) ;
do {
printf("Input a positive integer : ");
scanf("%d", &n);
if ( error = (n <= 0) )
printf("\nERROR : Do it again!\n\n");
} while ( error ) ; /* 음수가 입력되면 계속 수행 */
27
- do-while문에서는 { }를 생략해도 무방하나 사용을 권장함.
4.13 피보나치 수열 (Fibonacci Numbers)
- 재귀적 정의.
f0 = 0
f1 = 1
fi+1 = fi + fi-1,
for i = 1, 2 ...
(f0 = 1, f1 = 1로 정의하기도 함.)
- f0, f1을 제외하고 모든 원소는 이전 두 원소의 합.
(0,) 1, 1, 2, 3, 5, 8, 13, 21, 34, ......
28
/* print Fibonacci numbers and quotients. */
#include <stdio.h>
#define LIMIT 46
void main()
{
long f0 = 0, f1 = 1, n, temp;
/* 1st 2#'s */
printf("%7d%19d\n%7d%19d\n", 0, 0, 1, 1);
for ( n = 2; n <= LIMIT; ++n)
{
temp = f1;
f1 = f1 + f0;
f0 = temp;
printf("%7ld%19ld%29.16f\n", /* ld: long int */
n, f1, (double)f1 / f0);
}
}
29
- output
0
1
2
3
4
5
6
7
‥‥
23
24
25
‥‥
44
45
46
0
1
1
2
3
5
8
13
‥‥
23657
46368
75025
‥‥
701408733
1134903170
1836311903
1.0000000000000000
2.0000000000000000
1.5000000000000000
1.6666666666666667
1.6000000000000001
1.6250000000000000
‥‥
1.6180339901755971
1.6180339882053250
1.6180339889579021
‥‥
1.6180339887498949
1.6180339887498949
1.6180339887498949
30
n==41부터 quotient가 수렴
- manual execution
n
2
3
4
5
6
…
temp
1
1
2
3
5
…
f1
1
1
2
3
5
8
…
f0
0
1
1
2
3
5
…
quotient
1.0
2.0
1.5
1.66666666‥‥
1.6
…
31
- 자연과 피보나치 수열
꽃과 꽃잎, 식물의 잎에서 피보나치 수열을 찾을 수 있음.
식물뿐 아니라 고둥이나 소라의 나선구조에도 나타남.
이 수열은 ‘신의 비율’인 황금비를 만들어냄.
황금비는 피라미드 파르테논신전이나 다빈치 미켈란젤로의
작품에서 시작해 오늘날에는 신용카드와 담배갑의 가로 세로
비율까지 광범위하게 쓰임.
황금비는 태풍과 은하수의 형태, 초식동물의 뿔, 바다의 파도
에도 있음. 배꼽을 기준으로 한 사람의 상체와 하체, 목을 기
준으로 머리와 상체의 비율도 황금비
이 수열은 12세기 말 이탈리아 수학자 레오나르도 피보나치가
제안했다.
32
한 쌍의 토끼가 계속 새끼를 낳을 경우 몇 마리로 불어나는가를
숫자로 나타낸 것.
한 농장에서 갓 태어난 한 쌍의 아기 토끼가 사육되기 시작했다고 하자.한
쌍의 토끼는 생후 1개월 뒤 짝짓기를 하며 짝짓기한 뒤 1개월 뒤에 다시 한
쌍의 토끼를 생산한다고 하자.생산된 토끼가 죽지 않고 계속 산다면 일년 동
안 토끼는 몇 쌍이 될까’
0개월: 1쌍의 토끼
1개월 뒤: 여전히 1쌍의 토끼
2개월 뒤: 2쌍의 토끼 (1쌍의 토끼가 새로 태어나기 때문)
3개월 뒤: 3쌍의 토끼 (첫번째 암토끼가 다시 1쌍의 토끼 생산)
4개월 뒤: 5쌍의 토끼 (2마리의 암토끼가 각각 1쌍의 토끼 생산)
…….
1 1 2 3 5 8 13 21 34 55 89 144 233…
33
거의 모든 꽃의 꽃잎이 3장 5장 8장 13장…임.
백합, 아이리스, 붓꽃: 3장
채송화, 패랭이, 동백, 야생장미, 애기미나리아재비: 5장
모란, 코스모스, 참제비고깔: 8장
금불초, 금잔화, 시네라리아: 13장
애스터, 치코리: 21장
질경이, 데이지: 34장
쑥부쟁이: 종류에 따라 55장, 89장
34
고둥도 한 변의 길이가 피보나치 수열인 정사각형들이 만들어
낸 나선 모양을 하고 있음.
피보나치 수열은 해바라기나 데이지 꽃머리의 씨앗 배치에도
존재
최소 공간에 최대의 씨앗을 촘촘하게 배치하는 ‘최적의 수학적
해법’으로 꽃은 피보나치 수열을 선택
씨앗은 꽃머리에서 왼쪽과 오른쪽 두 개의 방향으로 엇갈리게
나선 모양으로 자리잡음.
데이지 꽃 머리에는 서로 다른 34개와 55개의 나선이 있고, 해
바라기 꽃머리에는 55개와 89개의 나선이 있음.
35
식물의 잎차례: 줄기에서 잎이 나와 배열하는 방식.
피보나치 수열이 가장 잘 나타남.
t/n으로 표시(t번 회전하는 동안 잎이 n개 나오는 비율)
참나무, 벚꽃 사과: 2/5
포플러 장미 배 버드나무는 3/8
갯버들과 아몬드는 5/13
전체 식물의 90%가 피보나치 수열의 잎차례를 따름.
잎이 바로 위의 잎에 가리지 않고 햇빛을 최대한 받을 수
있는 수학적 해법
36
황금비: 피보나치 수열을 만들어 냄. Fi / Fi-1
2/1 3/2 5/3 8/5…를 계속 계산하면 황금비에 수렴(2/1 3/2
5/3 8/5 … 1.6180339887498949…) ≒ 1.618
음악의 거장 바르톡은 피보나치 수열에 따라 음악의 마디를
나누고 황금분할점에 클라이막스를 두는 새로운 음악을 제창.
“전에는 식물의 DNA가 피보나치 수열을 만들어낸다고 생각했
으나, 요즘에는 식물의 씨앗이나 잎이 먼저 나온 씨나 잎을 비
집고 새로 자라면서 환경에 적응해 최적의 성장 방법을 찾아
가는 과정에서 자연스럽게 피보나치 수열에 이르는 것으로 생
각하고 있다. 특히 최근에는 생물뿐 아니라 전하를 입힌 기름
방울을 순서대로 떨어뜨려도 해바라기 씨앗처럼 퍼진다는 사
실이 밝혀지면서 피보나치 수열과 황금비가 생물은 물론 자연
과 우주 어디에나 숨어있다고 믿는 수학자가 더욱 늘고 있다”
(서울대 김홍종 교수(수학))
http://www.donga.com/fbin/searchview?n=200205190092
37
숙제
9. 정수 n을 입력하여 n번째 Fibonacci Number를 출력하는
program을 작성하라. 단 첫번째 Fibonacci Number는
0 으로 간주한다.
38
4.14 goto문
- 절대로 사용하지 말것
- 숙제에서 goto가 발견되면 무조건 'F'
39
4.15 break문과 continue문
- 정상적인 제어의 흐름을 중단시킴.
- break;
loop의 내부나 switch문에서 빠져나오게 함.
(예)
while ( 1 ) {
scanf("%lf", &x);
if ( x < 0.0)
break;
......
}
/* break jumps to here */
40
- continue: for, while, do loop 내에서만 사용
loop의 현재 반복을 중단하고 즉시 다음 반복을 수행.
(예)
for ( i = 0; i < TOTAL; ++i) {
c = getchar( );
if ( c >= '0' && c <= '9')
continue;
...... /* 숫자에 대해서는 아래의 처리를 않음 */
/* continue jumps to here to begin next iteration */
}
- break : loop를 종료.
continue : 현재 반복의 끝 부분으로 제어를 전달.
41
4.16 switch문
- if-else문을 일반화한 다중조건문.
(예)
scanf("%c", &i);
switch ( i ) {
case 'a' : ++ a_count; break;
case 'b' : ++ b_count; break;
case 'c' :
case 'C' : ++ c_count; break;
default : ++ other_count;
}
- switch(x)의 x는 반드시 정수적형 임.
- break; 문이 없으면 label과 관계없이 다음 문장을 수행.
42
(예) 장학금
1등 : 수업료 + 기성회비 + 학생회비
2등 : 기성회비 + 학생회비
3등 : 학생회비
switch ( i ) {
/* break문 없음 */
case 1 : 장학금 = 장학금 + 수업료;
case 2 : 장학금 = 장학금 + 기성회비;
case 3 : 장학금 = 장학금 + 학생회비;
}
switch ( i ) {
/* break문 사용 */
case 1 : 장학금 = 장학금 + 수업료 + 기성회비 + 학생회비;
break;
case 2 : 장학금 = 장학금 + 기성회비 + 학생회비;
break;
case 3 : 장학금 = 장학금 + 학생회비;
break;
default : ;
43
}
4.17 조건부 연산자
expr1 ? expr2 : expr3
(예)
x = ( y < z ) ? y : z;
if ( y < z )
x = y;
else
x = z;
44
숙제
10. 요일 찾기 program을 switch문을 사용하여 작성하라.
11. The Gettysbug Address 내의 alphabet 각각의 사용
빈도를 count 하는 program을 작성하라.
단, 대-소문자는 구분하지 않으며 alphabet 이외의 문자
(공백 문자, 구두점 등)는 'others'로 취급하라.
45