이전에 함수는 return으로 실행이 끝나고 값이 반환되며 함수에는 매개변수가 있다고 했지만 반환되는 값이 없는 함수나 매개변수가 없는 함수가 있을 수 있다.
예를 들어 화면을 나누어 주는 줄(-------)을 여러개 출력하는 함수를 만들면 매개변수나 반환값이 필요가 없다.
키보드로 수를 입력하면 양수로 반환하는 함수를 만든다면 scanf로 바로 입력을 받는 것으로 작성하면 매개변수가 필요 없다.
▼ 입력한 수를 양수로 반환하는 함수
#include <stdio.h>
int get_num(); // 함수 선언
int main(){
int result;
result = get_num(); // 함수 호출, 반환값은 result에 저장
printf("반환값 : %d\n", result); // 반환값 출력
}
int get_num(){ // 매개변수가 없고 반환형만 있음
int num; // 키보드 입력값을 저장할 변수
printf("양수 입력 : ");
scanf("%d", &num); // 키보드 입력
return num; // 입력한 값 반환
}
매개변수는 필요 없지만 키보드로 입력받은 값을 반환해야 하기 때문에 반환형(int)는 필요하다.
함수에 매개변수가 없기 때문에 호출할 때 인수가 없다. (인수가 없어도 괄호는 생략할 수 없다.)
데이터를 받아서 화면에 출력하는 함수는 반환값이 필요 없다.
▼ 문자와 숫자를 인수로 받으면 문자를 숫자만큼 화면에 출력하는 함수
#include <stdio.h>
void print_char(char ch, int count); // 함수 선언
int main(){
print_char('@', 5); // 문자와 숫자를 주고 함수 호출
}
void print_char(char ch, int count){ // 매개변수는 있으나 반환형은 없음
for(int i = 0; i < count; i++) // i는 0부터 count-1까지 증가, count번 반복
printf("%c", ch); // 매개변수 ch에 받은 문자 출력
return; // 생략 가능
}
반환값이 없기 때문에 반환형은 void를 사용한다.
return문은 값 없이 단독으로 사용하거나 생략 가능하다. return문이 없어도 함수의 코드가 모두 실행되면 호출한 곳으로 자동으로 돌아간다.
return문을 만나면 호출한 곳으로 돌아가는 것을 이용하여 함수 실행 중간에 돌아가도록 사용할 수 있다.
▼ count 값이 10보다 큰 경우 바로 종료되는 함수
void print_char(char ch, int count){
if (count > 10) return; // 여기서 return하면 함수의 실행이 종료된다.
for(int i = 0; i < count; i++)
printf("%c", ch);
return; // 생략 가능
}
여기에서도 마지막 return은 생략 가능하다. 생략하게 되면 코드가 모두 실행되면 함수가 종료된다.
▼ 문자열을 여러 번 출력하는 함수
#include <stdio.h>
void print_lint(); // 함수 선언
int main()
{
print_line(); // 함수 호출
printf("학번 이름 전공 학점\n");
print_line(); // 함수 호출
}
void print_line(){
for(int i = 0; i < 50; i++) // 50번 반복하여 '-' 출력
printf("-");
printf("\n");
}
함수는 보통 다른 함수를 호출하는데 재귀호출 함수는 함수 안에서 자기 자신을 호출한다.
▼ apple을 출력하는 재귀호출 함수
void fruit() // 재귀호출 함수 정의
{
printf("apple\n");
fruit(); // 자신을 다시 호출
}
함수가 모든 명령을 수행하면 자동으로 종료가 되는데 종료되기 전에 자신을 호출하므로 fruit함수가 처음부터 다시 시작한다.
따라서 실행 결과는 수많은 apple을 출력하다가 종료된다. -> 정상적이 종료가 아님
정상적으로 종료하기 위해 반복을 끝낼 조건식이 반드시 포함되어야 한다.
▼ 3번 실행되는 재귀호출 함수1
# include <stdio.h>
void fruit(int count);
int main()
{
fruit(1); // 처음 호출하므로 1을 인수로 줌
}
void fruit(int count) // 호출 횟수를 매개변수에 저장
{
printf("apple\n");
if (count == 3) return; // 호출 횟수가 3이면 반환하고 함수가 종료된다.
fruit(count +1); // 재호출할 때 호출 횟수를 1 증가
}
재귀호출을 사용하지 않고 반복문을 사용해도 되지 않을까?
▼ 3번 실행되는 재귀호출 함수2
# include <stdio.h>
void fruit(int count);
int main()
{
fruit(1); // 처음 호출하므로 1을 인수로 줌
}
void fruit(int count) // 호출 횟수를 매개변수에 저장
{
printf("apple\n");
if (count == 3) return; // 호출 횟수가 3이면 반환하고 함수가 종료된다.
fruit(count +1); // 재호출할 때 호출 횟수를 1 증가
printf("jam\n"); // <--- 추가
}
fruit 함수에 출력문 하나를 추가하였을 때 실행 결과를 예측하면 retrun문으로 함수가 종료되면 jam이 출력되지 않을 것이라고 생각할 수 있다.
하지만 실행 결과는 jam이 2번 출력된다.
apple
apple
apple
jam
jam
재귀호출 함수는 바로 직전에 호출했던 곳으로 돌아가기 때문이다. 재귀호출이 수행될때마다 함수의 복사본이 만들어진다고 생각하자
재귀호출은 코드를 반복 실행하는 것이 아니라 새로운 함수를 실행하는 것이다.
재귀호출 함수를 이용하여 복잡한 반복문을 간단히 표현할 수 있지만 코드 읽기가 어렵고 메모리 사용량이 많아져서 제한적으로 사용해야 한다.