4 장제어의흐름 박종혁교수 UCS Lab Tel: 970-6702 Email: jhpark1@seoultech.ac.kr SeoulTech 2018-1 st 프로그래밍입문 (1)
2 목차 4.1 관계, 등가, 논리연산자 4.2 관계연산자와수식 4.3 등가연산자와수식 4.4 논리연산자와수식 4.5 복합문 4.6 수식과공백문장 4.7 if 와 if-else 문 4.8 while 문 4.9 for 문 4.10 예제 : 부울변수 4.11 콤마연산자 4.12 do 문 4.13 예제 : 피보나치수열 4.14 goto 문 4.15 break 문과 continue 문 4.16 switch 문 4.17 조건부연산자
3 제어의흐름 제어의순차적흐름 - 프로그램의문장은일반적으로순차적으로실행됨 동작의선택, 반복을위해순차적흐름을변경할필요가있음 선택 : if, if-else, switch 반복 : while, for, do 이러한구문에관계, 등가, 논리연산자가사용됨
4 관계, 등가, 논리연산자 관계연산자 보다작다 : < 보다크다 : > 보다작거나같다 : <= 보다크거나같다 : >=
5 관계, 등가, 논리연산자 등가연산자 같다 : == 같지않다 :!= 논리연산자 ( 단항 ) 부정 :! 논리곱 : && 논리합 :
6 참과거짓 C에서거짓은 0 값으로나타내고, 참은 0 아닌다른값으로나타냄 거짓의값은임의의 0 값이될수있음 0, 0.0, 널문자 '\0', NULL 포인터값 참값은임의의 0이아닌값 a < b와같은수식은참이나거짓의값을가짐 이수식은참이면정수값 1을, 거짓이면정수값 0 을생성
7 관계연산자 다음관계연산자는모두이항연산자임 < > <= >= 관계수식의값 a - b a < b a > b a <= b a >= b 양수 영 음수 0 0 1 1 0 0 0 1 1 1 1 0
8 관계수식예제 선언및초기화 char c = 'w'; int i = 1, j = 2, k = -7; double x = 7e+33, y = 0.001; 수식 동일한수식 결과값 'a' + 1 < c - i - 5 * j >= k + 1 3 < j < 5 x -3.333 <= x + y x < x + y ('a' + 1) < c ((-i) - (5 * j)) >= (k + 1) (3 < j) < 5 (x - 3.333) <= (x + y) x < (x + y) 1 0 1 1 0
9 등가연산자 등가수식의값 값 ex1 - ex2 ex1 == ex2 ex1!= ex2 zero nonzero 1 0 0 1 a!= b 와!(a == b) 는동일한수식 ( 주의 ) a == b 와 a = b 는유사하지만, 완전히다른수식임 if (a = 1)......
10 등가수식예제 선언및초기화 int i = 1, j = 2, k = 3; 수식 동일한수식 결값 과 i == j i!= j i + j + k == -2 * -k j == i j!= i ((i + j) + k) == ((-2) * (-k)) 0 1 1 잘못된사용예 a = b /* an assignment statement */ a = = b - 1 /* space not allowed */ (x + y) =! 44 /* syntax error: equivalent to (x + y) = (!44) */
11 논리연산자 논리연산자! : 단항연산자 &&, : 이항연산자! 연산자 값 ex1 zero nonzero!ex1 1 0
12! 연산자 선언및초기화 char c = 'A'; int i = 7, j = 7; double x = 0.0, y = 2.3; 수식 동일한수식! c! c! (i - j)! (i - j)! i - j (! i) - j!! (x + y)! (! (x + y))! x *!! y (! x) * (!(! y)) 결과값 0 1-7 1 1
13 &&, 연산자 수식의값 값 ex1 ex2 ex1 && ex2 ex1 ex2 zero zero nonzero nonzero zero nonzero zero nonzero 0 0 0 1 0 1 1 1
14 &&, 연산자 선언및초기화 char c = 'B'; int i = 3, j = 3, k = 3; double x = 0.0, y = 2.3; 수식 i && j && k x i && j - 3 i < j && x < y i < j x < y 'A' <= c && c <= 'Z' c -1 == 'A' c + 1 == 'Z 동일한수식 (i && j) && k x (i && (j - 3)) (i < j) && (x < y) (i < j) (x < y) ('A' <= c) && (c <= 'Z') ((c - 1) == 'A') ((c + 1) == 'Z') 결과값 1 0 0 1 1 1
15 잘못사용된예 a! /* out of order */ a!= b /*!= is the token for the "not equal" operator */ a && /* one operand missing */ a l l b /* extra space not allowed */ a & b /* this is a bitwise operation */ &b /* the address of b */
논리연산자의사용예 #include <stdio.h> int main() { int a=10; printf(" 논리곱연산 : %d\n", (a>5) && (a<=15)); } printf(" 논리합연산 : %d\n", (a!=10) (a==20)); printf(" 논리부정연산 : %d\n",!((a-5)>0)); printf(" 피연산자가상수인경우 : %d\n", -3.4 && (a>0)); return 0; 논리곱연산 : 1 논리합연산 : 0 논리부정연산 : 0 피연산자가상수인경우 : 1
17 단축평가 결과가참인지거짓인지판명되면더이상다음수식을평가하지않음 expr1 && expr2 expr1 이거짓일때, 이수식은이미거짓이라는것이판명되고따라서 expr2 는평가되지않음 expr1 expr2 expr1 이참일때, 이수식은이미참이라는것이판명되고따라서 expr2 는평가되지않음
18 복합문 중괄호 {} 로묶여진선언문과문장 문장들을실행가능한하나의단위로그룹화함 선언문이복합문의시작부분에있으면, 그복합문을블록이라고함 복합문자체도하나의문장임 C 에서문법적으로한문장이들어가는자리에복합문을사용할 수있음 복합문의예 { a = 1; { b = 2; c = 3; } }
19 수식과공백문장 수식문장은수식다음에세미콜론이붙은것 세미콜론은수식을문장으로만듦 각문장은다음문장으로넘어가기전에완전히평가됨 공백문장은하나의세미콜론으로작성됨
20 수식과공백문장 공백문장은구문상으로는문장이필요하지만, 의 미상으로그문장이필요없을때유용 예 a = b; /* an assignment statement */ a + b + c; /* legal, but no useful work gets done */ ; /* an empty statement */ printf("%d\n", a); /* a function call */
21 if if 문의형식 if (expr) statement expr 이 0 이아니면 ( 참 ), statement 가실행됨 0 이면, statement 는실행되지않고다음문장으로제어가넘어감
22 if 예제 if (y!= 0.0) x /= y; if (c == ' ') { ++blank_cnt; printf("found another blank\n"); }
23 if-else 문 if-else 문의형식 if (expr) statement1 else statement2 expr 이 0 이아니면 ( 참 ), statement1 이실행되고, 0 이면, statement2 가실행됨
24 if-else 문 예제 if (x < y) min = x; else min = y;
25 if, if-else 예제 예제 1 if (c >= 'a' && c <= 'z') ++lc_cnt; else { ++other_cnt; printf("%c is not a } lowercase letter", c);
26 if, if-else 예제 예제 2 if (i!= j) { i += 1; j += 2; } ; else i -= j; /* syntax error */
27 if, if-else 예제 예제 3 if (a == 1) if (b == 2) printf("***\n"); 예제 4 if (a == 1) if (b == 2) if (a == 1) if (b == 2) printf("***\n"); else printf("###\n"); printf("***\n"); else printf("###\n");
if~else 구문을사용한비만도검사프로그램 - BMI 는체중을키의제곱으로나눈다 ( 단위가체중은 kg, 키는 m). - BMI 가 20 미만 : 저체중, 20~24.9 : 표준체중, 25 이상 : 과체중 #include <stdio.h> int main() { double weight, height; double bmi; } printf(" 몸무게를입력하세요 (kg) : "); scanf("%lf", &weight); printf(" 키를입력하세요 (cm) : "); scanf("%lf", &height); height = height / 100; bmi = weight / (height * height); printf(" 당신의 BMI 는 : %.1lf 입니다.\n", bmi); if(bmi>=20.0 && bmi<25.0) printf(" 표준체중입니다.\n"); else printf(" 체중관리가필요합니다.\n"); return 0;
if~else if~else 구문을사용한학점계산프로그램예 - 평균점수는실수값으로입력된다. - 평균이 90 점이상은 A, 90 점미만 80 점이상이면 B, 80 점미만 70 점이상이면 C, 그외는 F #include <stdio.h> int main() { double avg; char grade; printf(" 평균점수를입력하세요 : "); scanf("%lf", &avg); if(avg>=90.0) grade='a'; else if(avg>=80.0) grade='b'; else if(avg>=70.0) grade='c'; else grade='f'; printf(" 학점은 %c 입니다.\n", grade); } return 0;
30 while 문 일반적인형태 while (expr) statement next statement 동작단계 expr이 0이아니면 ( 참 ), statement가실행되고제어는다시 while 루프의시작부분으로다시전달됨 expr이 0( 거짓 ) 이면, 제어는 next statement로넘어감 ( 따라서 while 루프의몸체는 0번이상수행됨 )
31 while 문예제 옳은예제 while ((c = getchar())!= EOF) { if (c >= 'a' && c <= 'z') ++lowercase_letter_cnt; ++total_cnt; }
32 while 문예제 잘못된예제 while (++i < LIMIT) do { // do is not allowed j = 2 * i + 3; printf("%d\n", j); }
33 while 문예제 바람직하지않은코드 printf("input an integer : "); scanf("%d", &n); while (--n)... /* do something */
34 while 문예제 바람직한코드 printf("input an integer : "); scanf("%d", &n); while (--n > 0)... /* do something */
35 문자종류별로사용된문자의수를세는프로그램. /* count blanks, digits, letters, newlines, and others. */ #include <stdio.h> int main(void) { int blank_cnt = 0, c, digit_cnt = 0, letter_cnt = 0, nl_cnt = 0, other_cnt = 0;
while ((c = getchar())!= EOF) /* braces not necessary */ if (c == ' ') ++blank_cnt; else if (c >= '0' && c <= '9') ++digit_cnt; else if (c >= 'a' && c <= 'z' l l c >= 'A' && c <= 'Z') ++letter_cnt; else if (c == '\n') ++nl_cnt; else ++other_cnt; 36
37 printf("%10s%10s%10s%10s%10s%10s\n\n", "blanks", "digits", "letters", "lines", "others", "total"); printf("%10d%10d%10d%10d%10d%10d\n\n", blank_cnt, digit_cnt, letter_cnt, nl_cnt, other_cnt, blank_cnt + digit_cnt + letter_cnt + nl_cnt + other_cnt); return 0; } cnt_char < cnt_char.c 화면에나타나는출력은다음과같다. blanks digits letters lines others total 197 31 348 27 180 783
38 입력받은숫자구구단 // while 문을이용한구구단출력프로그램 #include <stdio.h> int main(void) { int n; int i = 1; printf( 출력하고싶은단 : "); scanf("%d", &n); } while (i <= 9) { printf("%d*%d = %d \n", n, i, n*i); i++; 출력하고싶은단 : 9 } 9*1 = 9 9*2 = 18 return 0; 9*3 = 27... 9*9 = 81
39 for 문 일반적인형태 for (expr1; expr2; expr3) statement next statement
40 동작단계 1. expr1 평가 /* 보통 expr1 은초기화를위해사용 */ 2. expr2 평가 /* 보통 expr2 는제어수단으로사용 */ 3. expr2 평가결과가 0 이아니면, 1) statement 실행 2) expr3 실행 /* 보통 expr3 은제어값을조정하기위해사용 */ 3) 2 단계부터다시실행 4. expr2 평가결과가 0 이면, 1) next statement 실행
41 for 의일반적인형태에서 expr2 를사용하고 statement 가 continue 를포함하고있지않다면, 다음과같은의미임 expr1; while (expr2) { statement expr3; } next statement
42 for 문예제 for (i = 1; i <= n; ++i) factorial *= i; for ( ; i <= 10; ++i) sum += i; for ( ; i <= 10; ) sum += i++; for ( ; ; ) { sum += i++; printf("%d\n", sum); }
43 예 for (i =1; i <=n; ++i) factorial *= i; for (j = 2; k % j == 0; ++j) { printf("%d is a divisor of %d\n", j, k); sum += j; } 잘못된사용예 for (i = 0, < n, i += 3) /*semicolons are needed */ sum += i;
44 for 문예제 1 에서 10 까지정수의합을계산. --> i = 1; sum = 0; for ( ; i <= 10; ++i) sum += i; --> i = 1; sum = 0; for ( ; i <= 10 ; ) sum += i++; i = 1; sum = 0; for ( ; ; ) { sum += i++; printf("%d\n", sum); }
45 n! 구하기 // 반복을이용한팩토리얼구하기 #include <stdio.h> int main(void) { long fact=1; int i, n; printf(" 정수를입력하시오 :"); scanf("%d", &n); for(i = 1;i <= n; i++) fact = fact * i; printf("%d! 은 %d 입니다.\n",n,fact); } return 0; 정수를입력하시오 : 10 10! 은 3628800 입니다.
46 피라미드출력 #include <stdio.h> int main() { int row; /* 행의개수 */ int col; /* 열의개수 */ int hight; /* 행과열의개수 */ printf(" 피라미드높이를입력하시오 : "); scanf("%d", &hight); for(row = 0; row < hight; row++) { for(col = 0; col <= row; col++) { printf("*"); } printf("\n"); } }
47 예제 : 부울변수 /* Print a table of values for some boolean functions. */ #include <stdio.h> int main(void) { int b1, b2, b3, b4, b5; /* boolean variables */ int cnt = 0; printf("\n%5s%5s%5s%5s%5s%5s%7s%7s%11s\n\n", /*headings */ "cnt", "b1", "b2", "b3", "b4", "b5", "fct1", "fct2", "majority");
48 } for (b1 = 0; b1 <= 1; ++b1) for (b2 = 0; b2 <= 1; ++b2) for (b3 = 0; b3 <= 1; ++b3) for (b4 = 0; b4 <= 1; ++b4) for (b5 = 0; b5 <= 1; ++b5) printf("%5d%5d%5d%5d%5d%5d%6d%7d%9d\n", ++cnt, b1, b2, b3, b4, b5, b1 ll b3 ll b5, b1 && b2 ll b4 && b5, b1 + b2 + b3 + b4 + b5 >= 3); putchar('\n'); return 0;
49 ==> 출력 cnt b1 b2 b3 b4 b5 fct1 fct2 majority 1 0 0 0 0 0 0 0 0 2 0 0 0 0 1 1 0 0 3 0 0 0 1 0 0 0 0...
50 콤마연산자 C 의모든연산자들중에서가장낮은우선순위를가짐 피연산자로수식을갖는이항연산자 좌에서우로의결합법칙 콤마수식의값은콤마연산자의오른쪽수식의값과형이됨 for 문에서많이사용 for (sum = 0, i = 1; i <= n; ++i) sum += i;
51 선언및초기화 int i, j, k = 3; double x = 3.3; 수식동일수식값 i = 1, j = 2, ++ k + 1 k!= 1, ++ x * 2.0 + 1 ((i = 1), (j = 2)), ((++k) + 1) (k!= 1), (((++ x) * 2.0) + 1) 5 9.6
52 do 문 일반적인형태 do statement while (expr); next statement 동작단계 1. statement 실행 2. expr 평가 3. expr 평가결과가 0 이아니면, 1) 1 단계부터다시실행 4. expr 평가결과가 0 이면, 1) next statement 실행
53 do 문 do 문은몸체부분을반드시한번이상실행해야할때유용 예제 i = 0; sum = 0; do { sum += i; scanf("%d", &i); } while (i > 0);
54 do 문예 양의정수만을읽는프로그램 do { printf("input a positive integer: "); scanf("%d", &n); if (error = (n <= 0)) printf("\nerror: Do it again!\n\n"); } while (error); float 형이나 double 형의식에대한등가검사는컴퓨터에서수표현의정확도때문에의도대로작동되지않을수있음
55 루프문을사용할때주의사항 예제 #include <stdio.h> int main(void){ int cnt = 0; double sum = 0.0, x; for (x = 0.0; x!= 9.9; x += 0.1) { // trouble! sum += x; printf("cnt = %5d\n", ++cnt); } printf("sum = %f\n", sum); return 0; }
56 goto 문 goto 문은현재함수내의레이블이붙은문장으로무조건분기함 다른제어흐름메커니즘 (for, while, do, if, switch) 들이제공하는모든유용한구조를파괴함 따라서가급적사용하지않는것이바람직함
57 레이블문장 레이블문장 bye: exit(1); L444: a = b + c; bug1: bug2: printf("bug found\n"); /* multiple labels */ 레이블은자신의이름영역을가짐 동일한식별자가레이블과변수모두로사용될수있음
58 goto 문예제 while (scant("%lf", &x) == 1) { if (x < 0.0) goto negative_alert; printf("%f %f\n", sqrt(x), sqrt(2 * x)); } negative_alert: printf("negative value encountered!\n");
59 break 문 루프나 switch 문에서사용되어제어를즉시루프다음문장으로전달 while (1) { scanf("%lf", &x); if (x < 0.0) break; negative */ printf("%f/n", sqrt(x)); } /* break jumps to here */ /* exit loop if x is
60 continue 문 루프내에서사용되어현재반복을멈추고즉시다음반복을하게함 for (i = 0; i < TOTAL; ++i) { c = getchar(); if (c >= '0' && c <= '9') continue;... /* process other characters */ /* continue transfers control to here to begin next iteration */ }
61 다음두코드는같은형태임 for (expr1; expr2; expr3) {... continue;... } expr1; while (expr2) {... goto next;... next : expr3; }
62 switch 문 switch 문은 if-else 문을일반화한다중조건문 switch 다음에오는괄화안에사용되는제어식은반드시정수형 제어식의평가결과에따라제어는해당되는 case 레이블로분기 예제 switch (c) { case 'a' : ++a_cnt; break; case 'b' : case 'B' : ++b_cnt; break; default : ++other_cnt; }
63 실행순서 1. switch 문의수식평가 2. 단계 1에서계산된값과일치하는상수값을갖는 case 레이블로분기 ; 만일그런 case 레이블이없다면, default 레이블로분기 ; 만일 default 레이블도없다면, switch 문종료 3. break 문을만나면, switch 문종료 ; 또는 switch 몸체의마지막문장을수행하면 switch 문종료
64 switch~case 구문을사용한추첨프로그램 #include <stdio.h> int main() { int lot; printf(" 당첨번호를입력하세요 : "); scanf("%d", &lot); switch(lot){ case 1: printf(" 김서방 "); break; case 2: printf(" 홍가네 "); break; case 3: printf(" 안산댁 "); break; default: printf(" 당첨자가없습니다!"); break; } } return 0;
65? : 조건부연산자 삼항연산자임 일반적인형태 expr1? expr2 : expr3 평가방법 1. expr1 평가 2. 참이면, expr2를평가하고그결과가이수식의값이됨 3. 거짓이면, expr3을평가하고그결과가이수식의값이됨 이수식의값은 expr2와 expr3에의해결정됨 만일이들의형이다르다면, 일반적인변환규칙이적용됨 즉, expr2나 expr3 중어떤것이평가되느냐에의존하지않음
66 선언및초기화 char a = 'a', b = 'b'; // a has decimal value 97 int i = 1, j = 2; double x = 7.07; 수식 동일한수식 결과값 형 i == j? a - 1 : b + 1 j % 3 == 0? i + 4 : x (i == j)? (a - 1) : (b + 1) ((j % 3) == 0)? (i + 4) : x 99 7.07 int double j % 3? i + 4 : x (j % 3)? (i + 4) : x 5.0 double
67 x = (y < z)? y : z; Declarations and initializations char a = 'a', b = 'b'; /* a has decimal value 97 */ int i = 1, j = 2; double x = 7.07; Expression Equivalent expression Value Type i == j? a -a1 : b + 1 (i == j)? (a -1) : (b + 1) 99 int j % 3 == 0? i + 4 : x ((j % 3) == 0)? (i + 4) : x 7.07 double j % 3? i + 4 : x (j % 3)? (i + 4) : x 5.0 double
68 같은의미수식 x = (y < z)? y : z; if (y < z) x = y ; else x = z;
69