[코딩도장] Unit 66 ~ 67
1. 함수 가변인자
1. 함수에서 가변인자 사용하기
함수의 들어가는 인수(argument)의 개수가 변하는 것을
가변 인자(variable argument)라고 한다
함수에서 가변 인자를 정의할 때는 고정 매개변수가 한 개 이상 있어야 한다
고정 매개변수 뒤에 ... 를 붙여 가변 인자를 정의할 수 있다
반환값자료형 함수이름(자료형 고정매개변수, ...)
{
}
... 으로 들어온 가변 인자를 사용하려면 <stdarg.h> 헤더 파일을 사용해야 한다
stdarg.h 에 정의된 가변 인자 처리 매크로는 아래와 같다
- va_list 가변인자 목록(가변 인자의 메모리 주소를 저장하는 포인터)
- va_start 가변 인자를 가져올 수 있도록 포인터를 설정
- va_arg 가변 인자 포인터에서 특정 자료형크기만큼 값을 가져옴
- va_end 가변 인자 처리가 끝났을 때 포인터를 NULL로 초기화
void printNumbers(int args, ...) // 가변 인자의 개수를 받음, ...로 가변 인자 설정
매개변수에서 인자의 개수를 받을 수 있도록 지정하고
두 번째 매개변수 부분에서 가변 인자를 받을 수 있도록 ...으로 지정한다
int main()
{
printNumbers(1, 10); // 인수 개수 1개
printNumbers(2, 10, 20); // 인수 개수 2개
printNumbers(3, 10, 20, 30); // 인수 개수 3개
printNumbers(4, 10, 20, 30, 40); // 인수 개수 4개
return 0;
}
printNumbers 함수를 호출할 때는 인수 개수를 넣어준 뒤
인수 개수에 맞게 인수를 콤마로 구분하여 넣어준다
va_list ap; // 가변 인자 목록 포인터
va_start(ap, args); // 가변 인자 목록 포인터 설정
printNumbers 함수 안에서
va_start 매크로에 가변 인자 포인터 ap 와 가변인자 개수 args 를 넣어준다
가변 인자 4개가 들어있는 printNumbers(4, 10, 20, 30, 40); 를 호출한 뒤
va_start 매크로를 실행하면 위와 같은 모양이 된다
for (int i = 0; i < args; i++) // 가변 인자 개수만큼 반복
{
int num = va_arg(ap, int); // int 크기만큼 가변 인자 목록 포인터에서 값을 가져옴
// ap를 int 크기만큼 순방향으로 이동
printf("%d ", num); // 가변 인자 값 출력
}
반복문으로 가변 인자 개수만큼 반복하면서 va_arg 매크로로 값을 가져온다
va_arg 에는 가변 인자의 자료형을 지정해준다
반복문에서 반복할 때마다 ap 는 4바이트씩 순방향 이동하므로
10, 20, 30, 40을 순서대로 가져올 수 있다
va_end(ap); // 가변 인자 목록 포인터를 NULL로 초기화
마지막으로 va_end 매크로를 사용하여 ap 를 NULL로 초기화 한다
2. 함수 재귀호출
1. 함수에서 재귀호출 사용하기
함수 안에서 자기자신을 호출하는 방식을 재귀호출(recursive call)이라고 한다
void hello()
{
printf("Hello, world!\n");
hello(); // hello 함수 안에서 hello 함수 호출
}
int main()
{
hello(); // hello 함수 최초 호출
return 0;
}
hello 함수 안에서 다시 hello 함수를 호출하는 코드이다
코드를 실행하면 hello 함수가 자기 자신을 계속 호출하다가
스택이 넘쳐 스택 오버플로우(stack overflow)에러가 발생한다
※ 재귀호출을 사용하려면 반드시 종료 조건을 만들어주어야 한다
void hello(int count)
{
if (count == 0) // count가 0이면 다시 hello 함수를 호출하지 않고 끝냄
return;
printf("Hello, world! %d\n", count);
hello(--count); // count를 감소시켜서 다시 hello에 넣음
}
함수의 반복 횟수를 계산하기 위해 매개변수 count를 넣어준다
count 가 0이 되면 함수를 종료한다
hello(5); // hello 함수 호출
main 함수에서는 hello 함수를 반복할 횟수를 넣어서 호출한다
3. 심사문제
66.6 가변 인자의 합 구하기
표준 입력으로 정수 두 개와 세 개가 입력됩니다. 다음 소스 코드를 완성하여 입력된 정수 두 개의 합과 세 개의 합이 출력되게 만드세요.
정답에는 밑줄 친 부분에 들어갈 코드만 작성해야 합니다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdarg.h>
int sum(int args, ...)
{
____________________
____________________
____________________
____________________
____________________
____________________
____________________
____________________
____________________
____________________
}
int main()
{
int num1, num2;
int num3, num4, num5;
scanf("%d %d", &num1, &num2);
scanf("%d %d %d", &num3, &num4, &num5);
printf("%d\n", sum(2, num1, num2));
printf("%d\n", sum(3, num3, num4, num5));
return 0;
}
정답
va_list ap;
int result = 0;
va_start(ap, args);
for (int i = 0; i < args; i++) {
result += va_arg(ap, int);
}
va_end(ap);
return result;
va_start 매크로로 가변 인자 목록 포인터를 사용한다
반복문을 사용하여 va_arg 매크로로 인자를 가져온 뒤
result 에 계속 더한다
66.7 가변 인자의 정수 합 구하기
표준 입력으로 정수 세 개가 입력됩니다. 다음 소스 코드를 완성하여 getSum 함수에 들어간 가변 인자 중에서 정수의 합을 구하도록 만드세요.
정답에는 밑줄 친 부분에 들어갈 코드만 작성해야 합니다.
- int : i
- double : d
- char * : s
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdarg.h>
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
int main()
{
int num1, num2, num3;
scanf("%d %d %d", &num1, &num2, &num3);
printf("%d\n", getSum("isi", num1, "C", 10));
printf("%d\n", getSum("sdsi", "Hello, world!", 5.3, "A", num2));
printf("%d\n", getSum("iiss", 25, 38, "k", "R"));
printf("%d\n", getSum("sidii", "Hello, C", num3, 2.234567, 878, 1291));
return 0;
}
정답
int getSum(char *types, ...) {
va_list ap;
int i = 0;
int result = 0;
va_start(ap, types);
while(types[i] != '\0') {
switch (types[i]) {
case 'i' :
result += va_arg(ap, int);
break;
case 'd' :
va_arg(ap, double);
break;
case 's' :
va_arg(ap, char *);
break;
}
i++;
}
va_end(ap);
return result;
}
정수 이외의 자료형은 합을 구하지 않는다고 해서
va_arg 매크로를 사용하지 않으면가변 인자 포인터 ap 가
다음 인자로 이동하지 않는다
67.6 재귀호출로 피보나치 수 구하기
표준 입력으로 정수 한 개가 입력됩니다(입력 값의 범위는 10~30) 다음 소스 코드를 완성하여 입력된 정수에 해당하는 피보나치 수가 출력되게 만드세요.
피보나치 수는 0과 1로 시작하며, 다음 번 피보나치 수는 바로 앞의 두 피보나치 수의 합입니다.
정답에는 밑줄 친 부분에 들어갈 코드만 작성해야 합니다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
_________________________
_________________________
_________________________
_________________________
_________________________
_________________________
_________________________
int main()
{
int num1;
scanf("%d", &num1);
printf("%d\n", fib(num1));
return 0;
}
정답
int fib(int n) {
if (n <= 1) {
return n;
}
return fib(n - 1) + fib(n - 2);
}
67.7 재귀호출로 1부터 n까지 합 구하기
표준 입력으로 정수 한 개가 입력됩니다.(입력 값의 범위는 3~100) 다음 소스 코드를 완성하여 1부터 입력된 정수까지의 합이 출력되게 만드세요. 단, 재귀호출을 사용해야 합니다.
정답에는 밑줄 친 부분에 들어갈 코드만 작성해야 합니다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int sum(int n)
{
if (n == 1)
return 1;
return _______________;
}
int main()
{
int n = 0;
scanf("%d", &n);
printf("%d\n", sum(n));
return 0;
}
정답
n + sum(n-1)
'Coding > C' 카테고리의 다른 글
[C언어] 파일 포인터 사용하기 - 코딩도장 (0) | 2024.03.06 |
---|---|
[C언어] 파일에서 문자열 읽고 쓰기 - 코딩도장 (0) | 2024.02.29 |
[C언어] 함수에서 매개변수 사용하기(포인터, 배열, 구조체) - 코딩도장 (0) | 2024.02.06 |
[C언어] 함수 사용하기 - 코딩도장 (0) | 2024.02.02 |
[C언어] 자료형 변환, 포인터 연산 - 코딩도장 (0) | 2024.01.30 |