함수(Function)
재사용 가능한 코드블럭으로, 특정 작업을 수행하는 명령문들의 집합.
함수는 입력을 받아서 특정 작업을 수행하고 결과를 반환.
프로그램을 작고 관리하기 쉬운 부분으로 나누어, 코드의 중복을 줄이고, 가독성을 향상.
함수의 기본 구조
반환형 함수이름 (매개변수){
// code block
;
return 반환값;
}
반환형(return type) : 반환할 자료형(datatype). 반환하지 않을때는 void
함수이름 : 함수를 식별하는 이름, 호출할때 사용된다.
매개변수(parameters list) : 함수에 전달될 매개변수 자료형과 이름.
매개변수가 없다면 비워둔다. 또는 void를 써준다.
함수본체(function body) : {} 중괄호 안에 들어가는 실행할 코드 블록.
Return 문 : 실행결과를 호출한 곳으로 반환.
void 함수에서는 return을 생략 할수 있다.
함수의 종류
표준 라이브러리 함수(Standard Library Functions): C 표준 라이브러리에 포함된 함수들로, 사용자는 이러한 함수들을 직접 정의할 필요 없이 사용할 수 있습니다. 예: printf(), scanf(), strcpy(), 등등.
사용자 정의 함수(User-Defined Functions): 사용자가 특정 작업을 수행하기 위해 직접 정의한 함수입니다.
example 1 - 함수의 기본 구조 예
매개변수와 반환값
위 예제에서 int num1, int num2이 매개변수(parameters)이다.
main 함수에서 int result = add(3, 5),
add(3, 5) : 함수호출(Function Call) 이라 한다.
3, 5 : 인수(Arguments)라 한다
정수 3은 num1에 대입된다. 정수 5는 num2에 대입된다.
함수호출시 인수는 매개변수와 같은 자료형(datatype)과 갯수를 가진다.
반환값
add 함수에서 반환값은 num1+num2의 결과이다.
add 함수에서 반환값은 반드시 int형이어야 한다. int add(…)로 선언했기때문.
반환값은 하나만 가능하다.
반환값이 없다면 함수 void로 선언한다.
void 함수는 반환값으로 return; 또는 return을 사용하지 않는다.
C 언어에서 식별자(identifier)는 변수, 함수, 배열 등의 이름을 말합니다.
알파벳 문자 또는 밑줄(_): 식별자는 알파벳 대문자(A-Z)나 소문자(a-z), 또는 밑줄(_)로 시작해야 합니다. 숫자로 시작할 수는 없습니다.
숫자 포함 가능: 식별자의 첫 글자 이후에는 숫자(0-9)가 포함될 수 있습니다.
특수 문자 불가: 알파벳, 숫자, 밑줄을 제외한 다른 특수 문자나 공백은 식별자에 사용할 수 없습니다.
키워드 사용 불가: C 언어에서 이미 의미가 정의된 키워드는 식별자로 사용할 수 없습니다. 예를 들어, int, return, for 등은 식별자로 사용할 수 없습니다.
길이 제한: 대부분의 컴파일러는 식별자의 유효한 길이를 제한합니다. 표준에는 구체적인 제한이 명시되어 있지 않지만, 일반적으로 첫 31자만을 유일한 식별자로 인식하는 것이 일반적입니다. 그 이상은 컴파일러나 플랫폼에 따라 다를 수 있습니다.
대소문자 구분: C 언어는 대소문자를 구분합니다. 예를 들어, Variable, variable, VaRiAbLe은 모두 다른 식별자로 간주됩니다.
좋은 식별자 이름 짓기 위한 관례
명확하고 의미 있는 이름: 변수나 함수의 용도를 쉽게 알 수 있도록 명확하고 의미 있는 이름을 사용합니다.
카멜케이스 또는 스네이크케이스: 두 단어 이상을 조합할 때는 카멜케이스(myVariable) 또는 스네이크케이스(my_variable)를 사용하여 가독성을 높입니다.
길이: 너무 긴 이름은 피하되, 너무 짧아서 의미를 파악하기 어렵지 않도록 합니다. 예를 들어, i는 반복문의 반복자로는 적합하지만, 다른 용도로는 더 명확한 이름을 사용하는 것이 좋습니다.
문맥에 맞는 이름: 변수나 함수가 사용되는 문맥에 맞는 이름을 사용합니다. 예를 들어, speed는 속도를 나타내는 변수에 적합한 이름입니다.
식별자 사용예
올바른 식별자의 예시:
int count;
double maxSpeed;
char* userName;
void printReport();
올바르지 않은 식별자의 예시:
int 2ndValue; // 숫자로 시작
char* user-name; // 하이픈 포함
void break(); // 키워드 사용
명명 규칙은 코드의 가독성과 유지보수성을 높이는 데 매우 중요합니다.
example 2 - 화씨2섭씨
example 3 - 소수 판단
함수 원형
C 언어에서 함수 원형(Function Prototype)은 함수의 선언을 의미합니다. 함수의 정의(implementation)를 함수가 호출되기 전에 미리 알려주는 역할을 합니다. 이를 통해 컴파일러가 함수 호출 시 함수의 반환 타입, 매개변수 타입, 개수 등을 미리 인지할 수 있습니다.
함수 원형의 필요성
C 언어는 기본적으로 함수가 정의된 위치 이후에만 해당 함수를 사용할 수 있습니다. 즉, 만약 함수가 정의된 위치 이전에 함수를 호출하려고 하면 컴파일러는 해당 함수를 찾을 수 없기 때문에 오류를 발생시킵니다. 이 문제를 해결하기 위해 함수 원형을 사용합니다.
예제 :
#include <stdio.h>
// 함수 원형 선언
int add(int, int);
int main() {
int result;
// 함수 호출
result = add(3, 4);
printf("결과: %d\n", result);
return 0;
}
// 함수 정의
int add(int a, int b) {
return a + b;
}
매개변수 이름이 선택사항인 이유
함수 원형에서는 매개변수의 타입만 중요하고, 실제 매개변수 이름은 함수의 정의에서만 사용되기 때문에 이름을 생략할 수 있습니다. 하지만 가독성을 위해 이름을 포함하는 것이 좋습니다.
example 4 - 함수원형 - compile error 수정하기
example 5 - prototype을 생략할 수 없는 경우
함수 원형과 헤더 파일
함수 원형 (Function Prototype)
함수 원형은 앞서 설명한 것처럼, 함수가 어떤 반환 값을 가지며 어떤 매개변수를 사용하는지 컴파일러에게 미리 알려주는 선언입니다. 함수 원형을 통해 컴파일러는 함수의 정의를 찾기 전에 함수가 어떻게 생겼는지 알 수 있습니다.
헤더 파일 (Header File)
헤더 파일은 보통 .h 확장자를 가지며, 함수 원형, 매크로, 데이터 타입 정의, 상수 등을 모아놓은 파일입니다. 헤더 파일을 사용하면 여러 소스 파일에서 공통적으로 사용할 내용들을 하나의 파일에 정의하여 코드의 재사용성을 높일 수 있습니다.
함수 원형과 헤더 파일의 관계
헤더 파일은 함수 원형을 선언하는 곳으로 자주 사용됩니다. 이를 통해 여러 소스 파일에서 동일한 함수 원형을 공유할 수 있습니다. 이렇게 하면, 소스 파일들 간에 함수 선언이 일관되게 유지되며, 코드 중복을 줄일 수 있습니다.
헤더 파일 사용 예제 :
아래는 함수 원형을 헤더 파일에 포함시키고 이를 소스 파일에서 사용하는 예제입니다.
<math_operations.h> (헤더 파일)
#ifndef MATH_OPERATIONS_H
#define MATH_OPERATIONS_H
// 함수 원형 선언
int add(int a, int b);
int subtract(int a, int b);
int multiply(int a, int b);
int divide(int a, int b);
#endif
<math_operations.c> (함수 정의)
#include "math_operations.h"
int add(int a, int b) {
return a + b;
}
int subtract(int a, int b) {
return a - b;
}
int multiply(int a, int b) {
return a * b;
}
int divide(int a, int b) {
if (b != 0)
return a / b;
else
return 0; // 0으로 나눌 경우의 예외 처리
}
<main.c> (메인 프로그램)
#include <stdio.h>
#include "math_operations.h"
int main() {
int x = 10, y = 5;
printf("덧셈: %d\n", add(x, y));
printf("뺄셈: %d\n", subtract(x, y));
printf("곱셈: %d\n", multiply(x, y));
printf("나눗셈: %d\n", divide(x, y));
return 0;
}
Compile :
gcc main.c math_operations.c -o main
코드 설명 :
1. math_operations.h : 함수 원형들을 선언한 헤더 파일입니다. 이 파일은 여러 소스 파일에서 공통적으로 사용할 함수 원형을 포함합니다.
- #ifndef, #define, #endif는 헤더 파일이 여러 번 포함되는 것을 방지하는 전처리기 지시문입니다. 이를 헤더 가드라고 합니다.
2. math_operations.c : 실제 함수들이 정의된 소스 파일입니다. 함수 원형은 헤더 파일에 포함되어 있으므로, 이 소스 파일에서는 함수의 정의만 하면 됩니다.
3. main.c : 메인 프로그램에서 #include "math_operations.h"를 통해 함수 원형을 가져와 사용합니다. 이로 인해, main.c에서 함수 호출 시 컴파일러는 해당 함수들의 반환 타입과 매개변수를 미리 알 수 있습니다.
표준 라이브러리 함수
C 언어의 표준 라이브러리는 다양한 표준 함수들의 집합.
다양한 운영 체제와 플랫폼에서 일관된 기능을 제공하기 위해 표준화 됨.
표준 라이브러리에는 데이터 처리, 메모리 할당, 수학 연산, 문자열 처리, 입출력 등 다양한 범주의 함수들이 포함한다.
표준 라이브러리의 각 함수들은 ANSI C 표준에 따라 정의되어 있으며, 이들은 대부분의 C 컴파일러와 함께 제공됩니다.
함수를 사용하기 전에 관련 헤더 파일을 포함시켜야 한다.
각 함수의 정확한 사용법과 매개변수, 반환 값은 해당 헤더 파일 내에서 문서화되어 있다.
자주 사용되는 표준 라이브러리
stdio.h (표준 입출력):
printf() - 화면에 텍스트를 출력합니다.
scanf() - 사용자로부터 입력을 받습니다.
fopen(), fclose() - 파일을 열고 닫습니다.
fprintf(), fscanf() - 파일에 텍스트를 쓰고 파일로부터 텍스트를 읽습니다.
getchar(), putchar() - 표준 입력으로부터 한 문자를 읽고 표준 출력에 한 문자를 씁니다.
stdlib.h (표준 유틸리티 함수):
malloc(), free() - 동적 메모리 할당과 해제를 합니다.
atoi(), atof() - 문자열을 정수나 부동 소수점 숫자로 변환합니다.
qsort() - 배열을 정렬합니다.
rand(), srand() - 난수를 생성하고 난수 생성기의 시드 값을 설정합니다.
string.h (문자열 처리):
strcpy(), strncpy() - 문자열을 복사합니다.
strcat(), strncat() - 두 문자열을 이어 붙입니다.
strcmp(), strncmp() - 두 문자열을 비교합니다.
strlen() - 문자열의 길이를 구합니다.
strchr(), strstr() - 문자열 내에서 문자나 부분 문자열을 찾습니다.
math.h (수학 함수):
pow() - 거듭제곱 값을 계산합니다.
sqrt() - 제곱근을 계산합니다.
sin(), cos(), tan() - 삼각 함수 값을 계산합니다.
log(), exp() - 로그와 지수 함수를 계산합니다.
time.h (시간 처리):
time() - 현재 시간을 가져옵니다.
difftime() - 두 시간의 차이를 계산합니다.
clock() - 프로그램이 사용한 처리기 시간을 측정합니다.
strftime() - 시간을 문자열로 포맷하여 출력합니다.
example 6 - 난수 생성
example 7 - 난수 생성 2
example 8 - racing_game.c
example 9 - math_etc.c
example 10 - system.c
example 11 - my_time.c
문제 1: 타이머 프로그램
사용자가 초 단위로 입력한 시간을 타이머로 구현하세요. 타이머가 0이 될 때까지 1초마다 시간을 감소시키고, 시간이 끝나면 "타이머 종료!"라는 메시지를 출력하세요.
요구사항 :
- 사용자가 초를 입력하면 그 시간을 카운트다운합니다.
- sleep(1) 또는 delay() 함수를 사용하여 1초마다 타이머를 감소시키세요.
- 타이머가 0이 되면 프로그램이 종료됩니다.
문제 2: 간단한 스톱워치
스톱워치 기능을 구현하세요. 사용자가 's'를 입력하면 시작, 'e'를 입력하면 종료되며, 경과된 시간을 초 단위로 출력합니다.
요구사항 :
- 사용자가 's'를 입력하면 시간이 기록됩니다.
- 'e'를 입력하면 스톱워치가 멈추고, 경과된 시간을 출력하세요.
- time() 함수를 사용하여 시작 시간과 종료 시간을 측정하세요.