반복문, 함수 컴퓨터시뮬레이션학과 2016년 봄학기 담당교수 : 이형원 E304호, hwlee@inje.ac.kr
지난주 요약 제어문은 문장을 순차적으로 실행하지 않고 필요에 따라 문장의 실행순서 를 제어해야 할 때 사용한다. 제어문은 문장을 순차적으로 실행하지 않고 필요에 따라 문장의 실행순서 를 제어해야 할 때 사용한다. if ~ else 문 if (조건식) 종속 문장 1; else 종속 문장 2; 다음 문장; 조건식이 거짓일 때의 흐름 조건식이 참일 때의 흐름
형식 swicth ~ case 문 switch ( 조건식 ) { 조건식이 값 2와 동일한 경우의 흐름 } 다음 문장; case 값 1: 문장 1; break; case 값 2: 문장 2; break; . case 값 n: 문장 n; break; default: 문장 n+1; } 다음 문장; swicth ~ case 문 조건식이 값 2와 동일한 경우의 흐름 먼저 값 1과 비교하여 일치하지 않으므로 다음 case로 이동한다. 먼저 값 2과 비교하여 일치하므로 뒤의 내용을 실행한다. break를 만나면 switch 문 다음 문장을 실행한다.
다음 주 과제 실습 모두 해볼 것 9장 읽어 올 것 숙제 해올 것
쉽게 풀어쓴 C언어 Express 제7장 반복문 C Express
이번 장에서 학습할 내용 반복의 개념 이해 while 반복문 do-while 반복문 for 반복문 반복 구조는 일련의 처리를 반복할 수 있게 한다. 반복의 개념을 먼저 이해하고 C에서 제공되는 3가지의 반복 구조에 대하여 학습한다. 반복의 개념 이해 while 반복문 do-while 반복문 for 반복문 break와 continue문
반복문 Q) 반복 구조는 왜 필요한가? A) 같은 처리 과정을 되풀이하는 것이 필요하기 때문이다. 학생 30명의 평균 성적을 구하려면 같은 과정을 30번 반복하여야 한다.
프로그램의 흐름을 제어하는 방법 순차 구조 선택 구조 반복 구조 차례대로 실행 조건을 검사하여 여러 개의 실행 경로 중에서 하나를 선택 반복 구조 조건이 만족될 때까지 반복
마일을 미터로 바꾸는 프로그램 같은 처리 과정 #1 같은 처리 과정 #2 같은 처리 과정 #3 #include <stdio.h> int main(void) { int meter; meter = 0 * 1609; printf("0 마일은 %d미터입니다\n", meter); meter = 1 * 1609; printf("1 마일은 %d미터입니다\n", meter); meter = 2 * 1609; printf("2 마일은 %d미터입니다\n", meter); return 0; } 같은 처리 과정 #1 같은 처리 과정 #2 같은 처리 과정 #3
반복문의 종류
중간 점검 1. 프로그램에 반복 구조가 필요한 이유는 무엇인가? 2. 반복문에는 _______, _______문이 있다.
while 문 주어진 조건이 만족되는 동안 문장들을 반복 실행한다. while( 조건식 ) 문장;
예제 1 2 3 i #include <stdio.h> int main(void) { int meter; int i = 0; while(i < 3) { meter = i * 1609; printf("%d 마일은 %d 미터입니다\n", i, meter); i++; } return 0; } 1 2 i 3 0 마일은 0 미터입니다 1 마일은 1609 미터입니다 2 마일은 3218 미터입니다
예제 // 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++; } return 0; } 구구단 중에서 출력하고 싶은 단을 입력하시오: 9 9*1 = 9 9*2 = 18 9*3 = 27 .... 9*9 = 81
예제 // while 문을 이용한 제곱값 출력 프로그램 #include <stdio.h> int main(void) { int n; printf("====================\n"); printf(" n n의 제곱 \n"); n = 1; while (n <= 10) { printf("%5d %5d\n", n, n*n); n++; } return 0; } ==================== n n의 제곱 1 1 2 4 3 9 4 16 5 25 6 36 7 49 8 64 9 81 10 100
예제 n이 무엇이 될지 모르는 경우라면 다음과 같이 계산 1부터 n까지의 합을 계산하는 프로그램 ... ①빈통을 준비한다. ②통에 1부터 n까지를 넣는다. ③통에 들어 있는 동전의 개수를 출력한다.
예제 #include <stdio.h> int main(void) { int i, n, sum; // 변수 선언 printf("정수를 입력하시오:"); // 입력 안내 메시지 출력 scanf("%d", &n); // 정수값 입력 i = 1; // 변수 초기화 sum = 0; while(i <= n) { sum += i; // sum = sum + i;와 같다. i++; // i = i + 1과 같다. } printf("1부터 %d까지의 합은 %d입니다\n", n, sum); return 0; } 정수를 입력하시오: 3 1부터 3까지의 합은 6입니다
예제 // while 문을 이용한 합계 프로그램 #include <stdio.h> int main(void) { int i, n, sum; i = 0; // 변수 초기화 sum = 0; // 변수 초기화 while (i < 5) { printf("값을 입력하시오: "); scanf("%d", &n); sum = sum + n; // sum += n;과 같다. i++; } printf("합계는 %d입니다.\n", sum); return 0; } 값을 입력하시오: 10 값을 입력하시오: 20 값을 입력하시오: 30 값을 입력하시오: 40 값을 입력하시오: 50 합계는 150입니다.
센티널(보초값의 이용) 100, 200, 300, 400, 500, -1 센티널: 입력되는 데이터의 끝을 알리는 특수한 값
성적들의 평균을 구하는 문제 1. 필요한 변수들을 초기화한다. 2. 성적을 입력받아서 합계를 구하고 성적의 개수를 센다. 성적의 평균을 구한다. 1. 필요한 변수들을 초기화한다. 2. 성적을 입력받아서 합계를 구하고 성적의 개수를 센다. 3. 평균을 계산하고 화면에 출력한다. 1. 필요한 변수들을 초기화한다. (1) sum을 0으로 초기화한다. (2) n을 0으로 초기화한다. (3) grade를 0으로 초기화한다.
성적들의 평균을 구하는 문제 while 성적이 0보다 작지 않으면 (1) 사용자로부터 성적을 읽어서 grade에 저장한다. 2. 성적을 입력받아서 합계를 구하고 성적의 개수를 센다. while 성적이 0보다 작지 않으면 (1) 사용자로부터 성적을 읽어서 grade에 저장한다. (2) sum에 이 점수를 누적한다. (3) n을 하나 증가한다. 3. 평균을 계산하고 화면에 출력한다. (1) sum을 n으로 나누어서 average에 저장한다. (2) average를 화면에 출력한다.
센티넬 예제 1/2 // while 문을 이용한 성적의 평균 구하기 프로그램 #include <stdio.h> int main(void) { int grade, n; float sum, average; // 필요한 변수들을 초기화한다. n = 0; sum = 0; grade = 0; printf("종료 시 음수 입력\n");
센티넬 예제 2/2 // 성적을 입력받아서 합계를 구하고 학생 수를 센다. while (grade >= 0) { { printf("성적을 입력하시오: "); scanf("%d", &grade); sum += grade; n++; } sum = sum - grade; // 마지막 데이터를 제거한다. n--; // 마지막 데이터를 제거한다. // 평균을 계산하고 화면에 출력한다. average = sum / n; printf("성적의 평균은 %f입니다.\n", average); return 0; } 성적 입력을 종료하려면 음수를 입력하시오 성적을 입력하시오: 10 성적을 입력하시오: 20 성적을 입력하시오: 30 성적을 입력하시오: 40 성적을 입력하시오: 50 성적을 입력하시오: -1 성적의 평균은 30.000000입니다.
예제: 최대값 #include <stdio.h> #include <limits.h> int main(void) { int number, min_value = INT_MAX; printf("정수를 입력하시오\n종료는 Ctrl+z\n"); while(scanf("%d", &number) != EOF) if( number < min_value ) min_value = number; } printf("최소값은 %d“, min_value); return 0; 정수를 입력하시오 종료는 Ctrl+z 10 20 30 5 ^Z 최소값은 5
예제 두수의 최대 공약수 구하기 유클리드 알고리즘 ① 두 수 가운데 큰 수를 x, 작은 수를 y라 한다. ② y가 0이면 공약수는 x와 같다. ③ r ← x % y ④ x ← y ⑤ y ← r ⑥ 단계 ②로 되돌아간다.
예제 // while 문을 이용한 최대 공약수 구하기 프로그램 #include <stdio.h> int main(void) { int x, y, r; printf("두개의 정수를 입력하시오(큰수, 작은수): "); scanf("%d%d", &x, &y); while (y != 0) { r = x % y; x = y; y = r; } printf("최대 공약수는 %d입니다.\n", x); return 0; } 두개의 정수를 입력하시오(큰 수, 작은 수): 12 8 최대 공약수는 4입니다.
if 문과 while 문의 비교 if( 조건 ) { ... } while( 조건 ) { ... } 조건이 만족되면 한번만 실행된다. 조건이 만족되면 여러 번 반복 실행된다.
while 문에서 주의할 점 변수가 증가 아니라 감소 반복 루프에 포함되어 있지 않다. 조건뒤에 ;이 있음 int i = 1; { printf("반복중입니다\n"): i--; } 변수가 증가 아니라 감소 int i = 0; while(i < 3) printf("반복중입니다\n"): i++; . 반복 루프에 포함되어 있지 않다. int i = 0; while(i < 3) ; { printf("반복중입니다\n"): i++; . } 조건뒤에 ;이 있음
참과 거짓 #include <stdio.h> int main(void) { int i = 3; while (i) printf("%d은 참입니다.", i); i--; } printf("%d은 거짓입니다.", i); 3은 참입니다. 2은 참입니다. 1은 참입니다. 0은 거짓입니다.
중간 점검 1. if 문과 while 문을 비교하여 보라. 똑같은 조건이라면 어떻게 동작하는가? 3. 다음 코드의 출력을 쓰시오. int n = 10; while (n > 0) { printf("%d\n", n); n = n - 3; }
실습: 반감기 반감기: 방사능 물질의 양이 ½로 되는 시간
실행 결과 단 로그 함수는 사용하지 않는다! 반복문을 사용한 다. 반감기를 입력하시오(년): 10 단 로그 함수는 사용하지 않는다! 반복문을 사용한 다. 반감기를 입력하시오(년): 10 10년 후에 남은 양=50.000000 20년 후에 남은 양=25.000000 30년 후에 남은 양=12.500000 40년 후에 남은 양=6.250000 1/10 이하로 되기 까지 걸린 시간=40년
알고리즘 사용자로부터 반감기를 입력받는다. while(물질의 양 > 초기 물질의 양*0.1) 반감기만큼 시간을 더한다. 물질의 양은 1/2로 줄어든다. 현재 물질의 양을 출력한다. 10% 이하로 되기까지 걸린 시간을 출력한다.
소스 #include <stdio.h> int main(void) { int halflife; double initial; double current; int years=0; printf("반감기를 입력하시오(년): "); scanf("%d", &halflife); initial = 100.0; current = initial; while( current > initial/10.0 ) years += halflife; current = current / 2.0; printf("%d년 후에 남은 양=%f", years, current); printf("1/10 이하로 되기까지 걸린 시간=%d년", years); return 0; }
도전문제 위와 비슷한 문제를 하나 더 작성해보자. 세균이 1시간마다 4배씩 증가한 다고 가정하자. 이 세균 10마리를 배양하면 7시간 후의 세균의 수는 얼마 나 될까? 역시 지수 함수나 로그 함수를 이용하지 말고 반복 구조만을 사용 하여서 해결하여 보자. 종이를 한번 접으면 면적이 1/2로 줄어든다. 종이를 몇 번 접어야 원래 면 적의 1/100로 줄어드는가? 역시 로그 함수나 지수 함수를 사용하지 말고 반복 구조를 이용하여서 해결하여 보자.
do...while문 반복 조건을 루프의 끝에서 검사 do 문장 while(조건)
do-while 문 적어도 한번은 반복문장을 실행한다.
예제 // do..while 문을 이용한 메뉴 1---새로만들기 #include <stdio.h> 2---파일열기 int main(void) { int i = 0; do { printf("1---새로만들기\n"); printf("2---파일열기\n"); printf("3---파일닫기\n"); printf("하나를 선택하시요.\n"); scanf("%d", &i); } while(i < 1 || i > 3); printf("선택된 메뉴=%d\n",i); return 0; } 1---새로만들기 2---파일열기 3---파일닫기 하나를 선택하시요. 1 선택된 메뉴=1
중간 점검 1. 다음 코드의 출력을 쓰시오. int n = 0; do { printf("%d\n", n); n = n + 3; } while(n < 10);
실습: 숫자 추측 게임 프로그램이 가지고 있는 정수를 사용자가 알아맞히는 게임 사용자가 답을 제시하면 프로그램은 자신이 저장한 정수와 비교하여 제시 된 정수가 더 높은지 낮은지 만을 알려준다.
실행 결과 정답을 추측하여 보시오: 10 제시한 정수가 낮습니다. 정답을 추측하여 보시오: 30 정답을 추측하여 보시오: 60 제시한 정수가 높습니다. 정답을 추측하여 보시오: 59 축하합니다. 시도횟수=4
알고리즘 do 사용자로부터 숫자를 guess로 입력받는다. 시도횟수를 증가한다. if( guess < answer ) 숫자가 낮다고 출력한다. if( guess > answer ) 숫자가 높다고 출력한다. while(guess != answer); “축하합니다”와 시도횟수를 출력한다.
소스 #include <stdio.h> int main(void) { int answer =59; // 정답 int guess; int tries = 0; do { printf("정답을 추측하여 보시오: "); scanf("%d", &guess); tries++; if (guess >answer) // 사용자가 입력한 정수가 정답보다 높으면 printf("제시한 정수가 높습니다."); if (guess <answer) // 사용자가 입력한 정수가 정답보다 낮으면 printf("제시한 정수가 낮습니다."); } while (guess !=answer); printf("축하합니다. 시도횟수=%d", tries); return 0;
도전문제 위의 프로그램이 게임이 되려면 난수를 발생시키는 것이 좋다. 난수는 (rand()%100)으로 발생이 가능하다. stdlib.h 헤더 파일도 포함시켜야 한 다.
for 루프 정해진 횟수만큼 반복하는 구조
for 문의 구조 for ( 초기식; 조건식; 증감식) 문장; ① 초기식을 실행한다. 문장; ① 초기식을 실행한다. ② 반복 조건을 나타내는 조건식을 계산한다. ③ 수식의 값이 거짓이면 for 문의 실행이 종료된다. ④ 수식의 값이 참이면 문장이 실행된다. ⑤ 증감식을 실행하고 ②로 돌아간다.
for 문의 구조 int i; for(i = 0; i < 10; i++) printf("Hello World!\n");
for문의 실행과정
for문의 실행과정 int i; for(i = 0; i < 10; i++) printf("Hello World!\n"); 반복횟수 i의 값 i<10 반복여부 1번째 반복 참 반복 2번째 반복 1 3번째 반복 2 4번째 반복 3 5번째 반복 4 6번째 반복 5 7번째 반복 6 8번째 반복 7 9번째 반복 8 10번째 반복 9 11번째 반복 10 거짓 중지
예제 // 반복을 이용한 정수합 프로그램 #include <stdio.h> int main(void) { // 반복을 이용한 정수합 프로그램 #include <stdio.h> int main(void) { int i, sum; sum = 0; for(i = 1;i <= 10; i++) sum += i; // sum = sum + i;와 같음 printf("1부터 10까지의 정수의 합= %d\n",sum); return 0; } 1부터 10까지의 정수의 합 = 55
예제 // 반복을 이용한 세제곱값구하기 정수를 입력하시요:5 #include <stdio.h> int main(void) { int i, n; printf("정수를 입력하시요:"); scanf("%d", &n); printf("====================\n"); printf(" i i의 세제곱\n"); for(i = 1;i <= n; i++) printf("%5d %5d\n", i, i*i*i); return 0; } 정수를 입력하시요:5 ==================== i i의 세제곱 1 1 2 8 3 27 4 64 5 125
예제 // 반복을 이용한 네모 그리기 #include <stdio.h> int main(void) { int i; printf("**********"); for(i = 0;i < 5; i++) printf("* *"); return 0; } ********** * * * *
예제 // 반복을 이용한 팩토리얼 구하기 #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입니다.
while 루프와 for 루프와의 관계 for ( ; while ( ) ; { ) { ... ... } ; ; ; ; ; } 초기식 초기식 ; while ( 조건식 ) 조건식 ; { 증감식 ) { 문장1 ; 문장1 ; 문장2 ; 문장2 ; ... ... 증감식 ; } }
팩토리얼 계산 예제(while 버전) // 반복을 이용한 팩토리얼 구하기 #include <stdio.h> int main(void) { long fact = 1; int i = 1, n; printf("정수를 입력하시요: "); scanf("%d", &n); while (i <= n) fact = fact * i; i++; } printf("%d!은 %d입니다.", n, fact); return 0; 정수를 입력하시요: 10 10!은 3628800입니다.
다양한 증감수식의 형태 뺄셈 사용 for (i = 0; i < 10; i += 2 ) printf("Hello World!\n"); 뺄셈 사용 for (i = 0; i < 10; i += 2 ) printf("Hello World!\n"); 2씩 증가 for (i = 1; i < 10; i *= 2 ) printf("Hello World!\n"); 2를 곱한다. for (i = 0; i < 100; i = (i * i) + 2 ) printf("Hello World!\n"); 어떤 수식이라도 가능
다양한 증감수식의 형태 for ( ; ; ) printf("Hello World!\n"); 무한 반복 루프 for ( ; i<100; i++ ) printf("Hello World!\n"); 한부분이 없을 수도 있다. for (i = 0, k = 0; i < 100; i++ ) printf("Hello World!\n"); 2개 이상의 변수 초기화 for (printf("반복시작”), i = 0; i < 100; i++ ) printf("Hello World!\n"); 어떤 수식도 가능
중간 점검 1. 다음 코드의 출력을 쓰시오. for(i = 1; i < 5; i++) printf("%d ", 2 * i); 2. 다음 코드의 출력을 쓰시오. for(i = 10; i > 0; i = i - 2) printf("Student%d\n", i);
중첩 반복문 중첩 반복문(nested loop): 반복문 안에 다른 반복문이 위치
예제 // 중첩 for 문을 이용하여 *기호를 사각형 모양으로 출력하는 프로그램 #include <stdio.h> int main(void) { int x, y; for(y = 0;y < 5; y++) { for(x = 0;x < 10; x++) printf("*"); printf("\n"); } return 0; } **********
예제 #include <stdio.h> int main(void) { int x, y; for(y = 1; y <= 5; y++) for(x = 0; x < y; x++) printf("*"); printf(""); // 내부 반복문이 종료될 때마다 실행 } return 0; * ** *** **** *****
중간 점검 printf("%d 곱하기 %d은 %d\n", i, j, i*j); 1. 다음 코드의 출력을 쓰시오. for(i = 1; i < 6; i++) for(j = 5; j >= 1; j--) printf("%d 곱하기 %d은 %d\n", i, j, i*j);
실습: 직각 삼각형 찾기 각 변의 길이가 100보다 작은 삼각형 중에서 피타고라스의 정리가 성립하 는 직각 삼각형은 몇 개나 있을까?
실행 결과 3 4 5 4 3 5 5 12 13 ...
알고리즘 for(a=1;a<=100;a++) for(b=1;b<=100;b++) for(c=1;c<=100;c++) if( a*a + b*b == c*c ) a와 b와 c를 화면에 출력한다.
소스 #include <stdio.h> int main(void) { int a, b, c; for(a=1; a<=100; a++) for(b=1; b<=100; b++) for(c=1; c<=100; c++) if( (a*a+b*b)==c*c ) printf("%d %d %d", a, b, c); return 0; }
도전문제 위와 비슷한 문제를 하나 더 작성해보자. 라스베가스와 같은 도박장에 가 면 주사위 게임이 있다. 주사위 2개를 던졌을 때, 합이 6이 되는 경우를 전 부 출력하여 보자. 예를 들어서 (1, 5), (2, 4),...와 같이 출력되면 된다. 또 주사위 3개를 사용하여서 합이 10이 되는 경우를 전부 출력하여 보자.
break 문 break 문은 반복 루프를 빠져 나오는데 사용된다. break 반복루프
예제 #include <stdio.h> #define SEED_MONEY 1000000 int main(void) { int year=0, money=SEED_MONEY; while(1) year++; money += money*0.30; if( money > 10*SEED_MONEY ) break; } printf("%d", year); return 0; 원금의 10배가 되면
예제 // break를 이용하여 무한루프를 탈출한다. #include <stdio.h> #include <math.h> int main(void) { double v; while(1) { printf("실수값을 입력하시오: "); scanf("%lf", &v); if( v < 0.0 ) break; printf("%f의 제곱근은 %f입니다.\n", v, sqrt(v)); } return 0; } 실수값을 입력하시오: 9.0 9.000000의 제곱근은 3.000000입니다. 실수값을 입력하시오: 12.0 12.000000의 제곱근은 3.464102입니다. 실수값을 입력하시오: 25.0 25.000000의 제곱근은 5.000000입니다. 실수값을 입력하시오: -1
goto문의 사용 OUT 으로 goto #include <stdio.h> int main(void) { int x, y; for(y = 1; y < 10000; y++) { for(x = 1; x < 50; x++) { if( _kbhit() ) goto OUT; printf("*"); } printf("\n"); } OUT: return 0; } OUT 으로 goto ************************************************* ***********
continue 문 현재의 반복을 중단하고 다음 반복을 시작하게 한다.
예제 #include <stdio.h> int main(void) { int i; for(i=0 ; i<10 ; i++) if( i%3 == 0 ) continue; printf("%d ", i); return 0; } 3의 배수 는 건너뛴다. 1 2 4 5 7 8
예제 // 소문자를 대문자로 변경한다. #include <stdio.h> int main(void) { char letter; while(1) { printf("소문자를 입력하시오: "); scanf(" %c", &letter); if( letter == 'Q' ) break ; if( letter < 'a' || letter > 'z' ) continue ; letter -= 32; printf("변환된 대문자는 %c입니다.\n", letter); } return 0; } 소문자를 입력하시오: a 변환된 대문자는 A입니다. 소문자를 입력하시오: b 변환된 대문자는 B입니다. 소문자를 입력하시오: c 변환된 대문자는 C입니다. 소문자를 입력하시오: Q
중간 점검 1. _______ 문이 반복문에서 실행되면 현재의 반복을 중단하고 다음번 반복 처리가 시작된다. 1. _______ 문이 반복문에서 실행되면 현재의 반복을 중단하고 다음번 반복 처리가 시작된다. 2. _______ 문이 반복문에서 실행되면 반복문을 빠져 나온다. 3. 다음 코드의 출력을 쓰시오. int i; for(i = 1; i < 10; i++) { if( i % 3 == 0 ) break; printf("%d\n", i); }
실습: 파이 구하기 파이를 계산하는 가장 고전적인 방법은 Gregory-Leibniz 무한 수열을 이 용하는 것
실행 결과 반복횟수:100000 Pi = 3.141583 계속하려면 아무 키나 누르십시오 . . .
알고리즘 사용자로부터 반복횟수 loop_count를 입력받는다. 분자 = 4.0; 분모 = 1.0; sum = 0.0; while(loop_count > 0) sum = sum + 분자 / 분모; 분자 = -1.0* 분자; 분모 = 분모 + 2.0; --loop_count; sum을 출력한다.
실습 코드 #include <stdio.h> int main(void) { double divisor, divident, sum; int loop_count; divisor = 1.0; divident = 4.0; sum = 0.0; printf("반복횟수:"); scanf("%d", &loop_count); while(loop_count > 0) { sum = sum + divident / divisor; divident = -1.0 * divident; divisor = divisor + 2; loop_count--; } printf("Pi = %f", sum); return 0;
예제 #include <stdio.h> int main(void) { int i, years; double total, rate, investment; printf("원금: "); scanf("%lf", &investment); printf("이율(%%): "); scanf("%lf", &rate); printf("기간(년): "); scanf("%d", &years); printf("=================="); printf("연도 원리금");
예제 total = investment; rate /= 100.0; for(i = 0; i < years; i++) total = total * ( 1 + rate ); // 새로운 원리금 계산 printf("%2d %10.1f", i+1, total); return 0; } 원금: 1000000 이율(%): 8 기간(년): 10 ================== 연도 원리금 1 1080000.0 2 1166400.0 3 1259712.0 4 1360489.0 5 1469328.1 6 1586874.3 7 1713824.3 8 1850930.2 9 1999004.6 10 2158925.0
예제 #include <stdio.h> #define START_DAY 3 // 첫번째 날이 수요일 #define DAYS_OF_MONTH 31 // 달의 일수 int main(void) { int day, date; printf("=====================\n"); printf("일 월 화 수 목 금 토\n"); printf("=====================\n");
예제 // 월요일부터 수요일까지 for(day = 0; day < START_DAY ; day++) printf(" "); // 공백 출력 for(date = 1; date <= DAYS_OF_MONTH ; date++) { if( day == 7 ) { day = 0; // 일요일이면 줄바꿈을 출력 printf("\n"); } day++; printf("%2d ", date); // 날을 출력한다. } printf("\n=====================\n"); return 0; }
Q & A
쉽게 풀어쓴 C언어 Express 제8장 함수 C Express
규모가 큰 프로그램은 전체 문제를 보다 단순하고 이해하기 쉬운 함수로 나누어서 프로그램을 작성하여야 한다. 이번 장에서 학습할 내용 규모가 큰 프로그램은 전체 문제를 보다 단순하고 이해하기 쉬운 함수로 나누어서 프로그램을 작성하여야 한다. 모듈화 함수의 개념, 역할 함수 작성 방법 반환값 인수 전달 함수를 사용하는 이유
모듈의 개념 모듈(module) 모듈러 프로그래밍 모듈러 프로그래밍의 장점 C에서는 모듈==함수 독립되어 있는 프로그램의 일부분 모듈러 프로그래밍 모듈 개념을 사용하는 프로그래밍 기법 모듈러 프로그래밍의 장점 각 모듈들은 독자적으로 개발 가능 다른 모듈과 독립적으로 변경 가능 유지 보수가 쉬워진다. 모듈의 재사용 가능 C에서는 모듈==함수
함수의 개념 함수(function): 특정한 작업을 수행하는 독립적인 부분 함수 호출(function call): 함수를 호출하여 사용하는 것 함수는 입력을 받으며 출력을 생성한다.
함수의 필요성 #include <stdio.h> int main(void) { int i; for(i = 0; i < 10; i++) printf("*"); ... return 0; } 10개의 *을 출력하는 코드 10개의 *을 출력하는 코드 10개의 *을 출력하는 코드
함수의 필요성 함수를 정의하였다. 함수는 한번 정의되면 여러 번 호출하여서 실행이 가능하다. #include <stdio.h> void print_star() { int i; for(i = 0; i < 10; i++) printf("*"); } int main(void) print_star(); ... return 0;
함수의 장점 함수를 사용하면 코드가 중복되는 것을 막을 수 있다. 한번 작성된 함수는 여러 번 재사용할 수 있다. 함수를 사용하면 전체 프로그램을 모듈로 나눌 수 있어서 개발 과정이 쉬 워지고 보다 체계적이 되면서 유지보수도 쉬워진다.
함수들의 연결 프로그램은 여러 개의 함수들로 이루어진다. 함수 호출을 통하여 서로 서로 연결된다. 제일 먼저 호출되는 함수는 main()이다.
함수의 종류
중간 점검 함수가 필요한 이유는 무엇인가? 함수와 프로그램의 관계는? 컴파일러에서 지원되는 함수를 __________함수라고 한다.
함수의 정의 반환형(return type) 함수 헤더(function header) 함수 몸체(function body)
함수의 구조
반환형
매개 변수
함수 정의 예제 함수를 프로그램을 이루는 부품이라고 가정하자. 입력을 받아서 작업한 후에 결과를 생성한다.
반환값: int / 함수 이름: square / 매개 변수: int n 예제 #1 정수의 제곱값을 계산하는 함수 반환값: int / 함수 이름: square / 매개 변수: int n int square( int n ) { return(n*n); }
반환값: int / 함수 이름: get_max / 매개 변수: int x, int y 예제 #2 두개의 정수중에서 큰 수를 계산하는 함수 반환값: int / 함수 이름: get_max / 매개 변수: int x, int y int get_max(int x, int y) { if( x > y ) return(x); else return(y); }
반환값: void / 함수 이름: draw_rect / 매개 변수: int side 예제 #3 별표 기호를 이용하여 정사각형을 그리는 함수 반환값: void / 함수 이름: draw_rect / 매개 변수: int side void draw_rect(int side) { int x, y; for(y = 0; y < side; y++) { for(x = 0; x < side; x++) printf("*"); printf("\n"); } return; }
반환값: int / 함수 이름: power / 매개 변수: int x, int y 예제 #4 정수의 거듭 제곱값(xy)을 계산하는 함수 반환값: int / 함수 이름: power / 매개 변수: int x, int y int power(int x, int y) { int i; long result = 1; for(i = 0; i < y; i++) result *= x; return result; }
반환값: int / 함수 이름: factorial / 매개 변수: int n 예제 #5 팩토리얼값(n!)을 계산하는 함수 반환값: int / 함수 이름: factorial / 매개 변수: int n int factorial(int n) { int i; long result = 1; for(i = 1; i <= n; i++) result *= i; // result = result * x return result; }
함수 호출과 반환 함수 호출(function call): 함수를 사용하기 위하여 함수의 이름을 적어주는 것 함수안의 문장들이 순차적으로 실행된다. 문장의 실행이 끝나면 호출한 위치로 되돌아 간다. 결과값을 전달할 수 있다.
인수와 매개 변수 2 3 x y 인수(argument): 실인수, 실매개 변수라고도 한다. 매개 변수(parameter): 형식 인수, 형식 매개 변수라고도 한다. 매개 변수 int main(void) { ... sum = add(2, 3); } int add(int x, int y) { ... } 인수 2 3 x y
반환값 3 반환값(return value): 호출된 함수가 호출한 곳으로 작업의 결과값을 전달하는 것 인수는 여러 개가 가능하나 반환값은 하나만 가능 3 return 0; return(0); return x; return x*x+2*x+1;
반환값 // 정수의 제곱을 계산하는 함수 예제 #include <stdio.h> int square(int n); int main(void) { int result; result = square(5); printf("%d ", result); } int square(int n) return(n * n); 25 result 25 5 n
2 3 x y 반환값 두개의 정수를 입력하시오: 2 3 두 수 중에서 큰 수는 3입니다. / 두수 중에서 큰 수를 찾는 함수 예제 #include <stdio.h> int get_max(int x, int y); int main(void) { int a, b; printf("두개의 정수를 입력하시오: "); scanf("%d %d", &a, &b); printf("두수 중에서 큰 수는 %d입니다.", get_max( a , b )); return 0; } int get_max(int x, int y) if( x > y ) return(x); else return(y); 2 3 x y
예제 3 // 거듭 제곱 값을 구하는 예제 #include <stdio.h> int get_integer(void); int power(int x, int y); int main(void) { int a, b; a = get_integer(); b = get_integer(); printf("%d의 %d승은 %d입니다. ", a, b, power(a, b)); return 0; } // 사용자로부터 값을 입력받아서 반환 int get_integer(void) int n; printf("정수를 입력하시오: "); scanf("%d", &n); return n;
예제 3 정수를 입력하시오: 2 정수를 입력하시오: 3 2의 3승은 8입니다. // 거듭 제곱 값을 계산하여서 반환 int power(int x, int y) { int i; long result = 1; // 1로 초기화 for(i = 0; i < y; i++) result *= x; // result = result * x return result; }
조합(combination) 계산 함수 팩토리얼 계산 함수와 get_integer() 함수를 호 출하여 조합을 계산한다
예제 #include <stdio.h> int get_integer(void); int combination(int n, int r); int factorial(int n); int main(void) { int a, b; a = get_integer(); b = get_integer(); printf("C(%d, %d) = %d \n", a, b, combination(a, b)); return 0; } int combination(int n, int r) return (factorial(n)/(factorial(r) * factorial(n-r)));
예제 int get_integer(void) { int n; printf("정수를 입력하시오: "); scanf("%d", &n); return n; } int factorial(int n) int i; long result = 1; for(i = 1; i <= n; i++) result *= i; // result = result * i return result; 정수를 입력하시오: 10 정수를 입력하시오: 3 C(10, 3) = 120
중간 점검 인수와 매개 변수는 어떤 관계가 있는가? 반환값이 실수로 정의된 함수에서 실수로 정수를 반환하면 어떤 일이 발생 하는가?
실습: 소수 찾기 주어진 숫자가 소수(prime)인지를 결정하는 프로그램이다. 양의 정수 n이 소수가 되려면 1과 자기 자신만을 약수로 가져야 한다. 암호학에서 많이 사용
실행결과 정수를 입력하시오: 23 23은 소수입니다.
알고리즘 사용자로부터 정수를 입력받아서 변수 n에 저장한다. 약수의 개수를 0으로 초기화한다. for( i=1; i<=n ; i++ ) n을 i로 나누어서 나머지가 0인지 본다. 나머지가 0이면 약수의 개수를 증가한다. 약수의 개수가 2이면 정수 n은 소수이다.
소스 #include <stdio.h> int is_prime(int); int get_integer(void); main() { int n, result; n = get_integer(); result = is_prime(n); if ( result == 1 ) printf("%d은 소수입니다.\n", n); else printf("%d은 소수가 아닙니다.\n", n); return 0; }
소스 int get_integer(void) { int n; printf("정수를 입력하시오: "); 정수를 입력하시오: 23 scanf("%d", &n); return n; } int is_prime(int n) { int divisors = 0, i; for ( i = 1 ; i <= n ; i++ ) { if ( n%i == 0 ) divisors++; return (divisors == 2); 정수를 입력하시오: 23 23은 소수입니다.
도전문제 is_prime() 함수의 실행 속도를 바르게 하기 위하여 어떤 코드를 추가할 수 있는지 생각하여보자. 현재 버전은 검사하는 숫자가 매우 크면 비효율적이 다. 예를 들어서 1,000,000에 대하여 호출되면 백만 번 반복을 하여야 한 다. 한 가지 방법은 1보다 크고 n보다 작은 숫자 중에서 약수가 하나라도 발견되면 이미 n은 소수가 아니라고 생각하는 것이다. 이것을 코드로 작성 하여 추가하여 보자.
함수 원형 함수 원형(function prototyping): 컴파일러에게 함수에 대하여 미리 알 리는 것 int compute_sum(int n); int main(void) { int sum; sum = compute_sum(100); printf(“sum=%d \n”, sum); } int compute_sum(int n) int i; int result = 0; for(i = 1; i <= n; i++) result += i; return result; compute_sum()은 함수 이름이랬지… 컴파일러
함수 원형의 형식 반환형 함수이름(매개변수1, 매개변수2, ... ); 자료형만 적어주어도 됨! 함수 원형(function prototype) : 미리 컴파일러에게 함수에 대한 정보를 알리는 것 (예) int get_integer(void); int combination(int n, int r); int combination(int, int); 반환형 함수이름(매개변수1, 매개변수2, ... ); 자료형만 적어주어도 됨!
함수 원형을 사용하지 않는 예제 함수 정의가 함수 호출보다 먼저 오면 함수 원형을 정의하지 않아도 된다. int compute_sum(int n) { int i; int result = 0; for(i = 1; i <= n; i++) result += i; return result; } int main(void) int sum; sum = compute_sum(100); printf(“sum=%d \n”, sum); 함수 정의가 함수 호출보다 먼저 오면 함수 원형을 정의하지 않아도 된다. 그러나 일반적인 방법은 아니다.
함수 원형과 헤더 파일 보통은 헤더 파일에 함수 원형이 선언되어 있음
중간 점검 함수 정의의 첫 번째 줄에는 어떤 정보들이 포함되는가? 이것을 무엇이라 고 부르는가? 함수 정의의 첫 번째 줄에는 어떤 정보들이 포함되는가? 이것을 무엇이라 고 부르는가? 함수가 반환할 수 있는 값의 개수는? 함수가 값을 반환하지 않는다면 반환형은 어떻게 정의되어야 하는가? 함수 정의와 함수 원형의 차이점은 무엇인가? 함수 원형에 반드시 필요한 것은 아니지만 대개 매개 변수들의 이름을 추 가하는 이유는 무엇인가? 다음과 같은 함수 원형을 보고 우리가 알 수 있는 정보는 어떤 것들인가? double pow(double, double);
라이브러리 함수 라이브러리 함수(library function): 컴파일러에서 제공하는 함수 표준 입출력 수학 연산 문자열 처리 시간 처리 오류 처리 데이터 검색과 정렬
난수 함수 난수(random number)는 규칙성이 없이 임의로 생성되는 수이다. 난수는 암호학이나 시뮬레이션, 게임 등에서 필수적이다. rand() 난수를 생성하는 함수 0부터 RAND_MAX까지의 난수를 생성
예제: 로또 번호 생성하기 1부터 45번 사이의 난수 발생
실습 코드 #include <stdio.h> #include <stdlib.h> int main(void) { int i; for(i = 0; i < 6; i++) printf("%d ", rand()); return 0; } 41 18467 6334 26500 19169 15724 0에서 32767 사이의 정수로 생성
1부터 45 사이로 제한 printf("%d ", 1+(rand()%45)); 하지만 실행할 때마다 항상 똑같은 난수가 발생된다. 42 18 35 41 45 20
실행할 때마다 다르게 하려면 매번 난수를 다르게 생성하려면 시드(seed)를 다르게 하여야 한다. srand( (unsigned)time( NULL ) ); #include <stdlib.h> #include <stdio.h> #include <time.h> #define MAX 45 int main( void ) { int i; srand( (unsigned)time( NULL ) ); for( i = 0; i < 6; i++ ) printf("%d ", 1+rand()%MAX ); return 0; } 시드를 설정하는 가장 일반적인 방법은 현재의 시각을 시드로 사용하는 것이다. 현재 시각은 실행할 때마다 달라지기 때문이다.
실습: 자동차 게임 난수를 이용하여서 자동차 게임을 작성 사용자가 키를 누를 때마다 1초씩 주행하도록 하자. 주행 거리는 난수로 결정된다.
실행 결과 CAR #1:**** CAR #2: --------------------- CAR #1:******
알고리즘 난수 발생기를 초기화한다 for( i=0; i<주행시간; i++) 난수를 발생하여서 자동차1의 주행거리에 누적한다. 난수를 발생하여서 자동차2의 주행거리에 누적한다. disp_car()를 호출하여서 자동차1을 화면에 *표로 그린다. disp_car()를 호출하여서 자동차2을 화면에 *표로 그린다.
소스 #include <stdlib.h> #include <stdio.h> #include <time.h> void disp_car(int car_number, int distance); int main(void) { int i; int car1_dist=0, car2_dist=0; srand( (unsigned)time( NULL ) ); for( i = 0; i < 6; i++ ) { car1_dist += rand() % 100; car2_dist += rand() % 100; disp_car(1, car1_dist); disp_car(2, car2_dist); printf("---------------------\n"); getch(); } return 0; rand()를 이용하여서 난수를 발생한다. 난수의 범위는 %연산자를 사용하여서 0에서 99로 제한하였다.
소스 void disp_car(int car_number, int distance) { int i; printf("CAR #%d:", car_number); for( i = 0; i < distance/10; i++ ) { printf("*"); } printf("\n");
도전문제 위의 프로그램을 참고하여서 숫자야구 게임을 작성해보자. 숫자 야구 게임 은 1~9 까지의 숫자 중에서 3개를 뽑아서 문제를 낸다. 단 숫자가 중복되 면 안 된다. 예를 들어 029라고 하자. 사용자는 이 숫자를 맞추게 된다. 각 자리수와 숫자 가 모두 일치하면 스트라이크, 숫자만 맞으면 볼이라고 출력한다. 029 vs 092 -> 1스트라이크 2볼
우틸리티 함수 #include <stdlib.h> #include <stdio.h> 설명 exit(int status) exit()를 호출하면 호출 프로세스를 종료시킨다. int system(const char *command) system()은 문자열 인수를 운영 체체의 명령어 셀에게 전달하여서 실행시키는 함수이다. #include <stdlib.h> #include <stdio.h> int main( void ) { system("dir"); printf("아무 키나 치세요\n"); getch(); system("cls"); return 0; } C 드라이브의 볼륨에는 이름이 없습니다. 볼륨 일련 번호: 507A-3B27 c:\source\chapter02\hello\hello 디렉터리 2011-11-28 오후 04:32 <DIR> . 2011-11-28 오후 04:32 <DIR> .. 2011-11-16 오전 11:01 20 binary.bin ... 4개 파일 5,296 바이트 3개 디렉터리 69,220,450,304 바이트 남음 아무 키나 치세요
수학 라이브러리 함수
예제 // 삼각 함수 라이브러리 #include <math.h> #include <stdio.h> int main( void ) { double pi = 3.1415926535; double x, y; x = pi / 2; y = sin( x ); printf( "sin( %f ) = %f\n", x, y ); y = sinh( x ); printf( "sinh( %f ) = %f\n",x, y ); y = cos( x ); printf( "cos( %f ) = %f\n", x, y ); y = cosh( x ); printf( "cosh( %f ) = %f\n",x, y ); } 여러 수학 함수들을 포함하는 표준 라이브러리 sin( 1.570796 ) = 1.000000 sinh( 1.570796 ) = 2.301299 cos( 1.570796 ) = 0.000000 cosh( 1.570796 ) = 2.509178
예제 #include <stdio.h> #include <math.h> #define RAD_TO_DEG (45.0/atan(1)) int main(void) { double w, h, r, theta; printf("밑변과 높이를 입력하시오:"); scanf("%lf %lf", &w, &h); r = sqrt(w * w + h * h); theta = RAD_TO_DEG * atan2(h, w); printf("빗변= %f 각도= %f\n", r, theta); return 0; } 상수를 정의하는 전처리 명령문 밑변과 높이를 입력하시오: 10.0 10.0 빗변= 14.142136 각도= 45.000000
수학 라이브러리 함수들 abs(int x), fabs(double x) abs(-9) // 9를 반환 pow(double x, double y) 인수 x의 y-거듭제곱인 xy 을 계산한다. pow( 2.0, 3.0 ); // 8.0을 반환 sqrt(double x) 주어진 수의 제곱근을 구한다. 만약에 음수가 입력되면 오류가 발생한다. sqrt( 9.0 ); // 3.0을 반환 ceil(double x) ceil은 x보다 작지 않은 가장 작은 정수를 반환 ceil( -2.9 ); // -2.0을 반환 ceil( 2.9 ); // 3.0을 반환 floor(double x) floor()는 x보다 크지 않은 가장 큰 정수를 반환한다. floor( -2.9 ); // -3.0을 반환 floor( 2.9 ); // 2.0을 반환
중간 점검 90도에서의 싸인값을 계산하는 문장을 작성하여 보라. rand() % 10 이 계산하는 값의 범위는?
함수를 사용하는 이유 소스 코드의 중복을 없애준다. 한번 작성된 함수를 다른 프로그램에서도 사용할 수 있다. 한번 만들어진 함수를 여러 번 호출하여 사용할 수 있다. 한번 작성된 함수를 다른 프로그램에서도 사용할 수 있다. 복잡한 문제를 단순한 부분으로 분해할 수 있다. void print_heading(void) { printf("*************************************"); printf(" NAME ADDRESS PHONE "); } int main(void) // 출력이 필요한 위치 #1 print_heading(); ... // 출력이 필요한 위치 #2 int main(void) { ... read_list(); sort_list(); print_list(); }
Q & A