본문 바로가기
C Programming/연습 문제

[C언어 연습문제]강좌 19. Variadic functions in C(가변인자 함수 구현법)

by 희품 2019. 5. 17.
반응형


학습(Study) & 목표(Objective)


가변 인자 함수는 함수의 인자 값의 수가 변하는 함수를 의미합니다. C 프로그래밍에서 가변 인자 함수는 개발 중인 프로그램의 유연성 향상에 이바지하고 있습니다.


가변 인자 함수의 선언은 적어도 하나의 이름이 있는 변수의 선언으로 시작하고, 생략 부호를 마지막 인자로 사용합니다.


예를 들어 printf() 함수가 있습니다.

int printf(const char* format, ...);


과제(Task)


이 프로그램은 인자값의 합계, 인자값의 최솟값, 인자값의 최댓값을 구하는 3개의 가변 인자 함수 sum(), min(), max() 함수를 구현합니다. 첫 번째 인자로 가변 인자 함수의 인자 개수를 전달하고, 그 뒤에 가변인자가 들어오게 됩니다.


입력 형식(Input Format)

- 입력의 첫 줄에는 정수 number_of_test_cases입니다.

- 각각 3개, 5개, 10개의 서로 다른 요소의 테스트 구현을 인자로 전달하여 코드의 로직을 테스트합니다.

- Sample 입력과 사용자 정의 입력에 대해 코드를 테스트할 수 있습니다.

- 오류 로그는 테스트 구현에 전달된 매개변수를 출력합니다. 또한, 코드에 해당하는 합계, 최소, 최대 요소를 출력합니다.



제약 조건(Constraints)

1 <= number_of_test_cases <= 50

1 <= element <= 1000000


출력 형식(Output Format)

테스트 구현의 실행 결과가 올바르면, "Correct Answer"이 출력됩니다. 잘못된 결과이면 "Wrong Answer"이 출력됩니다.


입력 예제(Sample Input)

1


출력 예제(Sample Output)

Correct Answer

Correct Answer

Correct Answer


주어진 코드


주어진 코드는 잠겨있습니다. 수정하면 안 되고, 주어진 코드에서 Correct Answer이 항상 출력되도록 가변 인자 함수를 구현하는 곳이 목적입니다.

test_implementations_by_sending_three_elements()

test_implementations_by_sending_five_elements()

test_implementations_by_sending_ten_elements()


이렇게 3개의 오류 검사 함수와 3개의 오류검사 함수를 호출하는

int main ()

main 함수로 이루어져 있습니다. 임의의 요소를 만들어, 가변 임자 함수 sum(), max(), 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
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
#define MIN_ELEMENT 1
#define MAX_ELEMENT 1000000
 
int sum(int count, ...) {
}
 
int min(int count, ...) {
}
 
int max(int count, ...) {
}
 
int test_implementations_by_sending_three_elements() {
    srand(time(NULL));
    
    int elements[3];
    
    elements[0= rand() % (MAX_ELEMENT - MIN_ELEMENT + 1+ MIN_ELEMENT;
    elements[1= rand() % (MAX_ELEMENT - MIN_ELEMENT + 1+ MIN_ELEMENT;
    elements[2= rand() % (MAX_ELEMENT - MIN_ELEMENT + 1+ MIN_ELEMENT;
    
    fprintf(stderr, "Sending following three elements:\n");
    for (int i = 0; i < 3; i++) {
        fprintf(stderr, "%d\n", elements[i]);
    }
    
    int elements_sum = sum(3, elements[0], elements[1], elements[2]);
    int minimum_element = min(3, elements[0], elements[1], elements[2]);
    int maximum_element = max(3, elements[0], elements[1], elements[2]);
    fprintf(stderr, "Your output is:\n");
    fprintf(stderr, "Elements sum is %d\n", elements_sum);
    fprintf(stderr, "Minimum element is %d\n", minimum_element);
    fprintf(stderr, "Maximum element is %d\n\n", maximum_element);
    
    int expected_elements_sum = 0;
    for (int i = 0; i < 3; i++) {
        if (elements[i] < minimum_element) {
            return 0;
        }
        
        if (elements[i] > maximum_element) {
            return 0;
        }
        
        expected_elements_sum += elements[i];
    }
    
    return elements_sum == expected_elements_sum;
}
int test_implementations_by_sending_five_elements() {
    srand(time(NULL));
    
    int elements[5];
    
    elements[0= rand() % (MAX_ELEMENT - MIN_ELEMENT + 1+ MIN_ELEMENT;
    elements[1= rand() % (MAX_ELEMENT - MIN_ELEMENT + 1+ MIN_ELEMENT;
    elements[2= rand() % (MAX_ELEMENT - MIN_ELEMENT + 1+ MIN_ELEMENT;
    elements[3= rand() % (MAX_ELEMENT - MIN_ELEMENT + 1+ MIN_ELEMENT;
    elements[4= rand() % (MAX_ELEMENT - MIN_ELEMENT + 1+ MIN_ELEMENT;
    
    fprintf(stderr, "Sending following five elements:\n");
    for (int i = 0; i < 5; i++) {
        fprintf(stderr, "%d\n", elements[i]);
    }
    
    int elements_sum = sum(5, elements[0], elements[1], elements[2], elements[3], elements[4]);
    int minimum_element = min(5, elements[0], elements[1], elements[2], elements[3], elements[4]);
    int maximum_element = max(5, elements[0], elements[1], elements[2], elements[3], elements[4]);
    
    fprintf(stderr, "Your output is:\n");
    fprintf(stderr, "Elements sum is %d\n", elements_sum);
    fprintf(stderr, "Minimum element is %d\n", minimum_element);
    fprintf(stderr, "Maximum element is %d\n\n", maximum_element);
    
    int expected_elements_sum = 0;
    for (int i = 0; i < 5; i++) {
        if (elements[i] < minimum_element) {
            return 0;
        }
        
        if (elements[i] > maximum_element) {
            return 0;
        }
        
        expected_elements_sum += elements[i];
    }
    
    return elements_sum == expected_elements_sum;
}
int test_implementations_by_sending_ten_elements() {
    srand(time(NULL));
    
    int elements[10];
    
    elements[0= rand() % (MAX_ELEMENT - MIN_ELEMENT + 1+ MIN_ELEMENT;
    elements[1= rand() % (MAX_ELEMENT - MIN_ELEMENT + 1+ MIN_ELEMENT;
    elements[2= rand() % (MAX_ELEMENT - MIN_ELEMENT + 1+ MIN_ELEMENT;
    elements[3= rand() % (MAX_ELEMENT - MIN_ELEMENT + 1+ MIN_ELEMENT;
    elements[4= rand() % (MAX_ELEMENT - MIN_ELEMENT + 1+ MIN_ELEMENT;
    elements[5= rand() % (MAX_ELEMENT - MIN_ELEMENT + 1+ MIN_ELEMENT;
    elements[6= rand() % (MAX_ELEMENT - MIN_ELEMENT + 1+ MIN_ELEMENT;
    elements[7= rand() % (MAX_ELEMENT - MIN_ELEMENT + 1+ MIN_ELEMENT;
    elements[8= rand() % (MAX_ELEMENT - MIN_ELEMENT + 1+ MIN_ELEMENT;
    elements[9= rand() % (MAX_ELEMENT - MIN_ELEMENT + 1+ MIN_ELEMENT;
    
    fprintf(stderr, "Sending following ten elements:\n");
    for (int i = 0; i < 10; i++) {
        fprintf(stderr, "%d\n", elements[i]);
    }
    
    int elements_sum = sum(10, elements[0], elements[1], elements[2], elements[3], elements[4],
                           elements[5], elements[6], elements[7], elements[8], elements[9]);
    int minimum_element = min(10, elements[0], elements[1], elements[2], elements[3], elements[4],
                           elements[5], elements[6], elements[7], elements[8], elements[9]);
    int maximum_element = max(10, elements[0], elements[1], elements[2], elements[3], elements[4],
                           elements[5], elements[6], elements[7], elements[8], elements[9]);
    
    fprintf(stderr, "Your output is:\n");
    fprintf(stderr, "Elements sum is %d\n", elements_sum);
    fprintf(stderr, "Minimum element is %d\n", minimum_element);
    fprintf(stderr, "Maximum element is %d\n\n", maximum_element);
    
    int expected_elements_sum = 0;
    for (int i = 0; i < 10; i++) {
        if (elements[i] < minimum_element) {
            return 0;
        }
        
        if (elements[i] > maximum_element) {
            return 0;
        }
        
        expected_elements_sum += elements[i];
    }
    
    return elements_sum == expected_elements_sum;
}
int main ()
{
    int number_of_test_cases;
    scanf("%d"&number_of_test_cases);
    
    while (number_of_test_cases--) {
        if (test_implementations_by_sending_three_elements()) {
            printf("Correct Answer\n");
        } else {
            printf("Wrong Answer\n");
        }
        
        if (test_implementations_by_sending_five_elements()) {
            printf("Correct Answer\n");
        } else {
            printf("Wrong Answer\n");
        }
        
        if (test_implementations_by_sending_ten_elements()) {
            printf("Correct Answer\n");
        } else {
            printf("Wrong Answer\n");
        }
    }
    
    return 0;
}


답안 코드


주어진 검사함수와 main() 함수는 코드 길이도 길고, 변경도 불가능한 코드이기 때문에 생략하겠습니다.


가변 인자 함수 구현에 2가지 문제점이 있습니다. 첫 번째 문제는 이름이 정의된 인자가 존재해야 하고, 가변 인자만으로는 가변인 자가 몇 번 전달되었는지 직접 확인할 방법이 없습니다. 가변인 자가 있는지는 계속 확인할 수 있지만, 전달된 인자값 이후에 호출되는 값은 쓰레깃값이 호출됩니다. 첫 번째 매개변수로 매개 변수의 수를 전달하면 두 가지 문제가 모두 해결됩니다.


가변 인자 매개변수를 사용하기 위해서는 va_list와 va_start, va_arg, va_end를 사용하면 됩니다.

int sum(int count, ...)
{
    int sum = 0;
    va_list values;
    va_start(values, count);
    for (int i = 0; i < count; i++)
    {
        sum += va_arg(values, int);
    }
    va_end(values);
 
    return sum;
}
 
int min(int count, ...)
{
    int min = MAX_ELEMENT, test;
    va_list values;
    va_start(values, count);
    for (int i = 0; i < count; i++)
    {
        test = va_arg(values, int);
        if (min > test)
        {
         min = test;
        }
    }
    va_end(values);
 
    return min;
}
 
int max(int count, ...)
{
    int max = MIN_ELEMENT, test;
    va_list values;
    va_start(values, count);
    for (int i = 0; i < count; i++)
    {
        test = va_arg(values, int);
        if (max < test)
        {
            max = test;
        }
    }
    va_end(values);
 
    return max;
}

va_list 변수를 만들고, va_start(values, count) 를 수행합니다. 처리가 완료되면, va_end()를 해주어야 합니다.







반응형