내용 정리

 

함수는 크게 라이브러리 함수와

 

사용자 지정 함수로 나뉜다

 

라이브러리 함수는 6장의 링크를 참조하여 사용할 때 찾아보면 익숙해질 것이다.

 

 

이번 chapter에서는 사용자 지정 함수에 대해 공부해보자

 

 

 

간단한 예제를 통해서 사용자 지정 함수가 어떠한 것인지

 

함수는 어떻게 생겼는지 보자

 

 

 

사용자 지정 함수

 

예제로 간단한 1차원 배열 문제를 확인하고 넘어가려 한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//함수
 
//두 수중 큰 값 구하기
#include <stdio.h>
 
int find_larger(int first, int second)
{
    int larger;
    
    if (first > second)
        larger = first;
    else
        larger = second;
 
    return larger;
}
 
int main()
{
    int n1, n2, max;
 
    printf("첫 번째:");
    scanf("%d"&n1);
 
    printf("두 번째:");
    scanf("%d"&n2);
 
    max = find_larger(n1, n2);
    printf("%d, %d중큰 수는:%d\n",n1,n2,max);
 
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

 

 

main함수를 실행하다 도중에

find_larger(n1,n2)를 만나

n1, n2를 인자로 사용하여 find_larger을 호출한다.

 

find_larger함수가 실행되며, n1값은 first로 n2값은 second로 전달되어 저장된다.

 

이때n1 == first는 아니다!

전달하는 시점에 값을 전달해주는 것뿐이다.

 

find_larger은 int형 변수인 larger을 반환해주면서 함수가 끝나고

다시 함수를 호출했던 부분인 main함수로 돌아와서 계속 main함수를 진행한다.

 

 

 

※ 함수의 인수 전달 (값에 의한 전달, 주소에 의한 전달)

 

 

값에 의한 호출로는
함수를 호출할 때 전달하는 인자와
호출한 함수의 변수(전달받은 인자가 저장된 값)는 다른 변수이기 때문에

호출한 함수 내부에서 값을 변경하더라도
main함수에서는 그대로임...

예를 들어

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdio.h>
 
void sort(int first, int second)
{
    int temp;
 
    if (first > second)
    {
        temp = first;
        first = second;
        second = temp;
    }
    printf("\nsort함수의 정렬 결과 first: %d, second: %d\n\n", first, second);
    printf("first의 기억장소 주소: %u\n"&first);
    printf("second의 기억장소 주소: %u\n\n"&second);
}
 
int main()
{
    int n1 = 5000, n2 = 4000;
    
    printf("함수 호출 전 n1: %d, n2: %d\n", n1, n2);
    sort(n1, n2);
    printf("함수 호출 후 n1: %d, n2: %d\n\n", n1, n2);
 
    printf("n1의 기억장소 주소: %u\n"&n1);
    printf("n2의 기억장소 주소: %u\n"&n2);
    
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
 
값에 의한 호출 방식으로 함수의 인자를 전달하면
main함수의 변수 값을 다른 함수에서 변경 할 수 없다.

결과를 확인하면 sort함수에서는 숫자가 오름차순으로 정렬이 되었으나
sort함수를 호출 하고 나서 main함수의 숫자는 정렬이 안된것을 확인 할 수 있다.

이유는 변수가 전혀 다른 변수이기 때문이다.
전혀 다른 변수라는것은 변수가 저장 되어있는 기억장소의 주소를 확인하면 알 수 있다.
n1와 first의 변수의 주소가 다르다.

 

따라서 다른 함수에서 호출 한 함수의 변수를 변경하고 싶으면
변수의 주소를 함수에 전달하여야 한다!

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdio.h>
 
void sort(int *first, int *second)
{
    int temp;
 
    if (*first > *second)
    {
        temp = *first;
        *first = *second;
        *second = temp;
    }
    printf("\nsort함수의 정렬 결과 first: %d, second: %d\n\n"*first, *second);
    printf("first의 기억장소 주소: %u\n", first);  //&(*first)도 같은 표현
    printf("second의 기억장소 주소: %u\n\n", second);
}
 
int main()
{
    int n1 = 5000, n2 = 4000;
 
    printf("함수 호출 전 n1: %d, n2: %d\n", n1, n2);
    sort(&n1, &n2);
    printf("함수 호출 후 n1: %d, n2: %d\n\n", n1, n2);
 
    printf("n1의 기억장소 주소: %u\n"&n1);
    printf("n2의 기억장소 주소: %u\n"&n2);
 
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

 

main에서 sort(&n1,&n2)로 변수의 주소 전달
sort함수는 main주소를 전달받았으므로
간접 참조 연산자*를 이용해 주소가 아닌 값을 받아올 수 있다.


결과를 보면 main함수의 변수들이 정렬된 것을 볼 수 있다.
주소를 확인하면 main함수의 변수와 sort함수의 변수가 같은 것을 확인할 수 있다.
주소를 전달받았기 때문이다.

 

추후 포인터를 공부한다면 좀 더 쉽게 이해할 수 있을 것이다.

 

 

 

※ 배열을 인자로 함수에 전달하기

 

 

배열명도 포인터이므로 포인터처럼 사용하여 인자로 전달하면 된다.
결론이지만
이해해보자

배열의 원소 하나를 함수의 인자로 전달하는 방식으로 모든 원소를 함수에 넣는다.
이 방법 번거롭고 많은 함수 호출이 일어난다.

일단 예제

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//함수
//배열의 원소 하나하나를 인자로 전달
 
#include <stdio.h>
#define N 10
 
int find_larger(int first, int second);
 
int main()
{
    int freeze[N] = { 150-20-3050-5-120-510-12 };
    int i, max;
 
    max = freeze[0];
 
    for (i = 1; i < N; i++)
    {
        max = find_larger(max, freeze[i]);
    }
 
    printf("어는 점 목록:");
    for (i = 0; i < N; i++)
    {
        printf("%d ", freeze[i]);
    }
    printf("\n가장 높은 어는 점:%d\n", max);
 
    return 0;
}
 
int find_larger(int first, int second)
{
    if (first > second)
        return first;
    else
        return second;    
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

 

max = find_larger(max, freeze[i]);
함수 호출할 때 freeze배열의 원소 하나하나 find_larger함수에 넣어서 최댓값을 찾는다.

처음에 max = find_larger[0] 로 지정해 놓았기 때문에
함수에는 1번 원소부터 넣어서

find_larger(max,freeze[1]) => 0~1중 큰 값이 리턴
find_larger(max,freeze[2]) => 0~2중 큰 값이 리턴
find_larger(max,freeze[3]) => 0~3중 큰 값이 리턴
find_larger(max,freeze[4]) => 0~4중 큰 값이 리턴
...
find_larger(max,freeze[9]) => 0~9중 큰 값이 리턴

총 9번 함수를 호출하여 큰 값을 구한다.

 

 

원소 하나하나 인자로 전달하는 방법은 상당히 비효율적이다.
=> 배열 전체를 인자로 전달한다.

포인터를 배우지 않았지만, 배열명 = 포인터라고 알아두자

배열명인 freeze를 인자로 전달하면 배열 전체를 전달할 수 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//함수
//배열의 전체를 인자로 전달
#include <stdio.h>
#define N 10
 
int find_larger(int arr[]);
 
int main()
{
    int freeze[N] = { 150-20-3050-5-120-510-12 };
    int max,i;
 
    max = find_larger(freeze);
 
    printf("어는 점 목록:");
    for (i = 0; i < N; i++)
    {
        printf("%d ", freeze[i]);
    }
 
    printf("\n가장 높은 어는 점:%d\n", max);
 
    return 0;
}
 
int find_larger(int arr[])
{
    int larger;
    int i;
 
    larger = arr[0];
    for (i = 1; i < N-1; i++)
    {
        if (larger < arr[i])
            larger = arr[i];
    }
    return larger;    
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

 

max = find_larger(freeze);
freeze배열 전체를 인자로 전달하였다.

 

 

배열 이름인 freeze는 변수를 저장하고 있는 변수가 아니라
배열의 시작 부분을 가리키고 있는 주소와 같다.
위 그림을 보면 이해가 가능하다.

freeze를 인자로 전달하여 freeze [0~9]까지 접근이 가능하게 된다.

 

 

-정리-
원소 하나하나를 전달하는 방법에 비해 훨씬 효율적인 방법
배열명을 인자로 전달하면 된다.
배열명은 배열의 첫 시작 원소의 주소이다.

 

 

※ 난수 구하기

 

난수구하기 은근히 자주 사용하는데 이참에 정리해보자
JAVA,C++,C#,C,PYTHON 배울 때 모두 사용한 거 같다
좀 자세히 정리해봐야지

C언어의 난수 생성함수
rand() : 0~32767 범위 안의 임의의 값 반환
헤더파일 stdlib.h(standard library 맞나?) 필요

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
    int i, random;
    for (i = 1; i <= 5; i++)
    {
        random = rand();
        printf("%d번째 난수:%5d\n", i, random);
    }
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

 

계속 같은 결과 나온다. 41,18467,6334,26500,19169 계속 이 순서...
난수 맞니??

 

 

씨드 설정 함수인 srand를 설정하여 난수가 순서를 변경한다.
=> 씨드가 같으면 생성되는 난수의 순서가 동일하다.

default값은 1로
위에서 씨드를 설정하지는 않았지만 srand(1)로 설정이 되어있는 상태인 것이다.

하지만 씨드값을 프로그램을 실행할 때 매번 다르게 할 수 없다.
time함수를 이용하여 현재 시간으로 씨드값을
설정하면 매번 다르게 자동적으로 씨드값을 설정할 수 있다.

srand(time(NULL))  time 함수 사용하기 위해 time.h 헤더파일 필요

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
int main()
{
    int i, random;
 
    srand(time(NULL));
 
    for (i = 1; i <= 5; i++)
    {
        random = rand();
        printf("%d번째 난수:%5d\n", i, random);
    }
    return 0;
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

 

 

매번 다르다!! 이 정도는 돼야 난수라고 인정하지

 


스케일링
난수를 원하는 범위로 설정하는 방법
간단하다

rand() : 0~32767 이라고 했다.

rand()%6 을 하면 0부터 5까지 나오겠지
그럼 (rand()%6)+1 을 하면 1부터 6까지의 범위가 나온다. (주사위)

5~10은
(rand%6)+5

일반화
min~max는
(rand%(max-min+1)) + min

간단한 게임 만들기
컴퓨터가 숨긴 수 맞추기

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//컴퓨터가 숨긴 1~100 중의 정수를 맞히는 게임
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
int main()
{
    int begin = 1end = 100;
    int count = 0;
    int computer, user;
 
    srand(time(NULL)); //씨드 설정
 
    computer = (rand() % (end - begin + 1)) + begin//컴퓨터가 숨기는 수 생성
    
    do
    {
        printf("%d~%d중의 값입니다. 얼마일까요?"beginend);
        scanf("%d"&user);
 
        count++;
 
        if (user < computer)
            begin = user + 1;
        else
            end = user - 1;
    } while (user != computer);
 
    printf("\n%d를 %d번만에 맞췄습니다.\n", computer, count);
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

 

 

computer = (rand() % (end - begin + 1)) + begin;
이것만 이해하면 끝

 

 

 

 

 

 


연습 문제

 

8, 9번을 풀어보겠다.

 

문제8: 한 달 동안의 음성 통화 시간이 voice분이고 문자 전송 건수가 text건일 때 휴대폰 사용료 계산 방법을

사용해 휴대폰 사용료 charge를 구하는 프로그램을 작성하시오

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <stdio.h>
 
int voice(int time)
{
    int charge; //음성통화 요금
    
    if (time > 100//100분 초과
        charge = (100 * 100+ ((time - 100* 80);
    else
        charge = 100 * time;
 
    return charge;
}
 
int message(int num)
{
    int charge; //문자 요금
 
    if (num > 20//문자 20건 초과
        charge = (num - 20* 20;
    else
        charge = 0;
 
    return charge;
}
 
int main()
{
    int voice_time; //음성 통화 시간
    int message_num; //문자 전송 건수
    int voice_charge; //음성 통화 요금
    int message_charge; //문자 전송 요금
    int sum_charge; //총 요금
    int surtex; //부가세
 
    printf("음성 통화 시간은(분)? ");
    scanf("%d"&voice_time);
    printf("문자 전송 건수는? ");
    scanf("%d"&message_num);
 
    //함수 호출
    voice_charge = voice(voice_time);
    message_charge = message(message_num);
 
    sum_charge = voice_charge + message_charge + 10000;
    surtex = sum_charge*0.1;
 
    //출력
    printf("휴대폰 사용 요금 청구서\n");
    printf("=========================================\n");
    printf("음성 통화 시간 %d\n",voice_time);
    printf("문자 전송 건수 %d건\n", message_num);
    printf("-----------------------------------------\n");
    printf("기본요금\t\t\t%6d원\n"10000);
    printf("음성 통화료 %d분\t\t%6d원\n",voice_time,voice_charge);
    printf("문자 전송료 초과 %d건(20건 무료)%6d원\n", message_num-20, message_charge);
    printf("-----------------------------------------\n");
    printf("합계\t\t\t\t%6d원\n", sum_charge);
    printf("부가세(10%%)\t\t\t%6d원\n", surtex);
    printf("=========================================\n");
    printf("이번 달 요금\t\t\t%6d원\n", sum_charge+ surtex);
    
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

 

그냥 텍스트 줄 맞추는데 힘들었다.

 

 

 

문제9: 학생 N명의 퀴즈 점수 10,8,7,9,6,10,9,8,7이 저장된 배열 class에 대해 사용자의 점수가 입력되면 순위를 출력하는 프로그램을 작성하시오. 입력된 점수 my_score의 순위를 구하는 함수 rank를 정의해 사용하시오.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>
#define N 9
 
int rank(myscore, otherscore)
{
    if (myscore < otherscore) //더 높은 점수있으면 등수 1개 낮추기
        return 1;
    else                       //내가 더 높으면 등수 그대로
        return 0;
}
 
int main()
{
    int score;
    int my_rank = 1;
    int i;
    int class[N] = { 10879610987 };
 
    printf("사용자의 점수를 입력하세요: ");
    scanf("%d"&score);
 
    for (i = 0; i < N; i++//배열 원소 하나씩 함수에 전달
    {
        my_rank += rank(score, class[i]); //리턴 받은 수를 누적시키기
    }
    for (i = 0; i < N; i++)
    {
        printf("%3d"class[i]);
    }
    printf("과 비교\n");
    printf("내 등수 = %d등\n", my_rank);
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

 

포인터로 배열 전체를 함수에 인자로 전달하면 더 쉬울 것을 하나하나 전달하니까
변수 생각하는데 더 머리가 아프다.
아직 포인터 진도 안나갔으니 하나하나 전달하여 해결

 

+ Recent posts