# Function Prototype and Library Function (2/2)

**Contents**

---

**1️⃣** 함수 원형과 라이브러리 함수

---

## **1️⃣** 함수 원형과 라이브러리 함수

### **함수 원형**(Function Prototype)의 필요성

**<mark>💡요약: </mark> 함수 원형**(Function Prototype)은 함수가 사용되기 전에 컴파일러에게 함수의 정보를 알려주는 선언이다. 함수 원형이 없으면 **컴파일러가 함수 호출을 인식하지 못해 오류**(Error) 가 발생하게 된다. 이 문제는 함수 원형을 **main 함수 위에 추가**(Add Prototype above main)하여 해결할 수 있다.

아래의 코드를 실행하면 오류가 발생하게 된다.

1. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730785244834/0d84b89d-92dd-4648-9a63-150c1df9f585.png align="center")
    
    **오류 원인**(Error Cause): `main` 함수에서 `c_to_f` 함수를 호출하고 있지만, `c_to_f` 함수의 **원형**(Prototype)이 `main` 함수 앞에 선언되지 않아 **컴파일러**(Compiler)가 함수의 존재를 알지 못한다.
    
2. **함수 원형**(Function Prototype): 함수가 사용되기 전에 컴파일러에게 해당 함수의 **이름, 반환형, 매개변수 타입**을 알려주는 선언이다. **함수 원형**이 없다면, 컴파일러는 함수를 처음 호출할 때 그 함수가 존재하는지 알 수 없어서 오류를 발생시킨다.
    
3. **해결 방법**(Solution): `main` 함수 앞에 `c_to_f` 함수의 **원형**(Prototype)을 추가하면 컴파일 오류가 사라지게 된다. `double c_to_f(double c_temp);` 라는 선언을 `main` 함수 위에 넣으면 된다.
    

---

### **함수 원형**(Function Prototype)의 역할과 작성 방법

**<mark>💡요약: </mark>** 컴파일러가 함수 호출을 이해할 수 있도록 함수의 기본 정보를 미리 알려주는 선언을 함수 원형이라고 한다. 함수 정의 이전에 작성하며, 함수 원형에서는 매개변수의 이름을 생략할 수 있다.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730785439904/b2d70666-44b3-49b1-b298-b6d1b5034ca6.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730785513078/87def7c3-b0a7-4a99-ad82-1a923ed5001a.png align="center")

* **함수 원형의 구성 요소**(Components of Function Prototype)
    
    * 함수의 **이름**(Name), **매개변수**(Parameters), 그리고 **반환형**(Return Type)을 함수가 정의되기 전에 선언한다.
        
    * **함수 원형**은 실제 함수 정의와 거의 같지만, 매개변수의 이름은 생략해도 되고 **자료형만**(Only the Data Type) 작성할 수 있다.
        
* **함수 헤더와의 차이점**(Difference from Function Header):
    
    * 함수 원형은 함수의 헤더와 유사하지만, 함수의 실제 내용을 담지 않고 단순히 **세미콜론**(;)을 추가하는 것으로 끝난다.
        
    * 함수의 **헤더**(Header)는 실제 함수 정의에 포함되며, **함수 원형**(Prototype)은 함수 호출 전에 미리 선언하기 위한 것이다.
        

**💡예시 코드**:

* 함수 원형: `double c_to_f(double);`
    
* 함수 정의: `double c_to_f(double c_temp) { /* 함수 내용 */ }`
    
* 여기서 함수 정의에서는 매개변수 이름을 명시하지만, 함수 원형에서는 자료형만 적어도 괜찮다.
    

---

### **함수 원형을 사용하지 않는 경우**(Examples Without Function Prototypes) 발생할 수 있는 문제와 예외적인 상황  

**<mark>💡요약: </mark> 함수 원형**(Function Prototype)은 함수가 정의되기 전에 선언하는 것이 **일반적인 방법**(Standard Practice)이다. 함수 원형이 없으면 순환 호출이나 호출 순서에 따라 **컴파일 오류**(Compile Errors)가 발생할 수 있다. 특히 **순환 호출**(Mutual Recursion)과 같은 상황에서는 함수 원형이 필수적이다.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730785627194/8d8b9847-3b94-4ff8-90ea-da72e41e4d61.png align="center")

* **함수 정의가 먼저 오는 경우**(When Function Definition Comes First):
    
    * 첫 번째 예제에서는 `compute_sum` 함수가 **main 함수**(main function)보다 먼저 정의되어 있어서 **함수 원형**(Function Prototype)을 사용하지 않아도 문제가 발생하지 않습니다. 그러나 이 방법은 일반적이지 않는다.
        
    * 보통 함수 원형을 먼저 선언해 두는 것이 **가독성**(Readability)과 **유지보수**(Maintainability)에 좋다.
        

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730792132030/cbc60508-f043-48de-8122-9c47ff4435e2.png align="center")

* **순환 호출**(Mutual Recursion) 상황:
    
    * 두 번째 예제에서는 `sub1`과 `sub2` 함수가 서로 호출하는 **순환 호출**(Mutual Recursion) 구조이다. 이 경우 함수가 서로를 참조해야 하므로 **함수 원형 없이는 컴파일 오류**(Compile Error)가 발생할 수 있다.
        
    * 이러한 구조에서는 반드시 **함수 원형**(Function Prototype)을 사용하여 컴파일러가 두 함수의 존재를 인식하게 해야 한다.
        
* **오류 메시지**(Error Messages):
    
    * 두 번째 예제에서는 `sub2` 함수가 정의되기 전에 `sub1`에서 호출되므로 **정의되지 않았다는 오류**(Undefined Function Error)가 발생하였다. 이 문제는 함수 원형을 사용하여 해결할 수 있다.
        

---

### 중간 점검(Midpoint Check)

**<mark>💡요약:</mark>** **함수 정의**(Function Definition)와 **함수 원형**(Function Prototype)의 주요 차이점과 각각의 역할을 이해하는 것이 중요하다. 함수 원형을 통해 반환형과 매개변수 정보를 미리 알 수 있으며, 함수가 값을 반환하지 않는 경우 `void`를 사용하여 정의할 수 있다.

1\. **함수 정의의 첫 번째 줄에 포함되는 정보는 무엇인가?**

* 함수 정의의 첫 줄에는 **함수 이름**(Function Name), **반환형**(Return Type), **매개변수 타입**(Parameter Types) 등이 포함된다.
    
* 이러한 요소들은 **함수 원형**(Function Prototype)과 동일하게 나타나며, 함수가 어떤 값을 반환하고 어떤 인자를 받는지 컴파일러에게 알려준다.  
    

2\. **함수가 반환할 수 있는 값의 개수는?**

* C 언어에서 함수는 **하나의 값만 반환**(Only One Return Value)할 수 있다. 여러 개의 값을 반환하려면 포인터나 구조체를 사용해야 한다.  
    

3\. **함수가 값을 반환하지 않는다면 반환형은 어떻게 정의되어야 하는가?**

* 반환할 값이 없는 함수는 **void**를 반환형으로 정의한다.
    
* 예를 들어, `void print_message(void);`와 같이 `void` 키워드를 사용하여 값을 반환하지 않음을 명시할 수 있다.  
    

4\. **함수 정의와 함수 원형의 차이점은 무엇인가?**

* **함수 정의**(Function Definition)에는 함수의 실제 코드 구현이 포함된다.
    
* 반면에, **함수 원형**(Function Prototype)은 함수가 어떤 반환형과 매개변수를 가지는지 **<mark>미리 알려주는 선언</mark>**이며, 세미콜론(`;`)으로 끝난다.
    
* 함수 정의는 프로그램이 실행될 때 실제로 어떤 작업을 수행할지 결정하지만, 함수 원형은 컴파일러에게 함수의 존재를 미리 알려주는 역할을 한다..
    

### 5\. **다음과 같은 함수 원형을 보고 우리가 알 수 있는 정보는 무엇인가?**

```c
double pow(double, double);
```

* **반환형**(Return Type): `pow` 함수는 `double` 형 값을 반환한다.
    
* **함수 이름**(Function Name): 함수의 이름은 `pow`이다.
    
* **매개변수 타입**(Parameter Types): `pow` 함수는 두 개의 `double` 타입 인자를 받는다.
    
* 이 함수 원형을 통해 우리는 `pow` 함수가 두 개의 `double` 값을 인자로 받아 하나의 `double` 값을 반환하는 기능임을 알 수 있다.
    

`pow` **power**의 줄임말로, C 언어에서 사용되는 **수학 함수**이다. 이 함수는 **거듭제곱**(Exponentiation)을 계산하는 역할을 한다. 즉, 주어진 **밑(base)**과 **지수(exponent)**를 받아 **밑을 지수만큼 거듭제곱한 값**을 반환한다.

---

### **라이브러리 함수**(Library Function)

**<mark>💡요약: </mark> 라이브러리 함수**(Library Function)는 컴파일러가 제공하는 기본적인 함수들로, **입출력, 수학 연산, 문자열 처리, 시간 처리, 오류 처리, 데이터 검색과 정렬** 등의 다양한 기능을 포함한다. 이를 통해 개발자는 복잡한 기능을 쉽게 구현할 수 있게 된다.

![Library Functions In C | Header Files, Uses & More (+ Examples)](https://d8it4huxumps7.cloudfront.net/bites/wp-content/banners/2024/7/66aa42aac4621_library_functions_in_c.jpg?d=1200x800 align="left")

☑️**표준 입력과 출력**(Standard Input/Output):

* **입력**(Input)과 **출력**(Output)을 처리하는 함수들다. 예를 들어, `printf`와 `scanf` 함수는 화면에 출력하고 입력을 받는 데 사용된다.
    

☑️**수학 연산**(Mathematical Operations):

* 다양한 수학 계산을 위한 함수들이다. 예를 들어, 제곱을 구하는 `pow` 함수, 제곱근을 구하는 `sqrt` 함수 등이 있다. 이런 함수들은 `<math.h>` 헤더 파일에 포함되어 있다.
    

☑️ **문자열 처리**(String Manipulation):

* 문자열을 다루기 위한 함수들이다. 예를 들어, `strcpy`, `strlen`, `strcat` 등은 문자열 복사, 길이 확인, 문자열 연결 등의 작업을 수행한다.
    

☑️**시간 처리**(Time Handling):

* 시간과 날짜를 다루는 함수들이다. 예를 들어, `time` 함수는 현재 시간을 가져오는 데 사용된다. 이런 함수들은 `<time.h>` 헤더 파일에 포함되어 있다.
    

☑️**오류 처리**(Error Handling):

* 프로그램 실행 중 발생할 수 있는 오류를 처리하는 함수들이다. 예를 들어, `perror` 함수는 오류 메시지를 출력하는 데 사용된다.
    

☑️**데이터 검색과 정렬**(Data Searching and Sorting):

* 배열 등의 데이터를 검색하거나 정렬하는 함수들이다. 예를 들어, `qsort`는 배열을 정렬하고, `bsearch`는 배열에서 값을 찾는 데 사용된다.
    

---

### **난수 함수**(Random Number Function)

**<mark>💡요약: </mark>** 난수는 규칙성이 없는 **임의의 수**(Random Number)로, **암호학, 시뮬레이션, 게임**과 같은 다양한 분야에서 필수적으로 사용된다. 이 중에서 **rand() 함수**(rand function)는 C 언어에서 **임의의 수**(Random Number)를 생성하는 기본 함수로, 0에서 `RAND_MAX` 사이의 값을 반환한다.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730793562331/32dcf2c5-7669-4681-9d42-a84cc9366f74.png align="center")

* **난수**(Random Number):
    
    * 난수는 예측할 수 없는 임의의 수로, 규칙성이 없다. **암호학**(Cryptography)이나 **시뮬레이션**(Simulation), **게임**(Games)에서 자주 사용된다.
        
* **rand() 함수**:
    
    * `rand()` 함수는 C 언어에서 난수를 생성하는 함수이다.
        
    * `rand()` 함수는 0부터 `RAND_MAX`까지의 정수 난수를 반환한다. `RAND_MAX`는 `rand()` 함수가 반환할 수 있는 최대 값으로, 컴파일러마다 다를 수 있다.
        

**<mark>💡예제: 기본 예제: 0부터 </mark>** `RAND_MAX` **<mark> 사이의 난수 생성</mark>**

```c
#include <stdio.h>
#include <stdlib.h>

int main() {
    printf("난수 생성: %d\n", rand());  // 0에서 RAND_MAX 사이의 난수 생성
    return 0;
}
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730793860555/2b53a815-7078-47e3-98f2-f38927092cc6.png align="center")

* 이 예제는 `rand()` 함수를 사용하여 0에서 `RAND_MAX` 사이의 임의의 정수 난수를 출력한다.
    

---

### 예제: 로또번호 생성하기 (Generate lottery number)

**<mark>💡첫번째 시도:</mark>** **로또 번호 생성**(Generating Lotto Numbers) 프로그램을 작성하려면 **1에서 45 사이의 난수**를 생성해야 한다. 기본 예제 코드에서는 `rand()` 함수를 사용해 난수를 생성하지만, 로또 범위에 맞게 수정이 필요하다.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730793612720/2d7c95ca-6b2e-4bc5-bb67-7318b99d92ec.png align="center")

* **로또 번호 생성 규칙**:
    
    * 로또 번호는 **1부터 45 사이의 숫자**(Numbers Between 1 and 45)로 구성된다.
        
    * 이 숫자들은 **6개**가 필요하며, 필요에 따라 보너스 번호를 추가할 수 있다.
        
* **기본 난수 생성 코드**:
    
    * 예제 코드에서는 `rand()` 함수를 사용하여 6개의 난수를 생성한다.
        
    * `rand()` 함수는 0에서 **32767 사이의 난수**(Random Number Between 0 and 32767)를 생성한다. 하지만 로또 번호 범위는 1부터 45이므로, 이 코드는 수정이 필요하다
        

```c
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int i;
    for (i = 0; i < 6; i++) {
        printf("%d ", rand());  // rand() 함수로 난수 생성
    }
    return 0;
}
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730794323569/f36b9889-aa02-4247-8df6-ca7e4e8fe067.png align="center")

* 이 코드는 `rand()` 함수를 사용해 6개의 난수를 출력하였다. 하지만 **1부터 45 사이의 숫자가 아니라 0에서 32767 사이**의 숫자를 생성하였다.
    
* 로또 번호 생성에 적합한 값을 얻기 위해서는 `rand() % 45 + 1`과 같이 범위를 제한해야 한다.
    

---

**<mark>💡두번째 시도: </mark>** 난수를 1부터 45로 제한하는 방법이다. `rand()` 함수는 기본적으로 0에서 `RAND_MAX`까지의 값을 반환하므로, 특정 범위로 제한하려면 추가적인 계산이 필요하다. |

* **1부터 45 사이 난수 생성**:
    
    * `printf("%d ", 1 + (rand() % 45));` 코드를 사용하여 **1부터 45 사이의 난수**를 생성할 수 있다.
        
    * `rand() % 45`는 0에서 44까지의 값을 생성하고, 여기에 1을 더하여 **1부터 45 사이의 값**을 얻는다.
        

```c
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int i;
    for (i = 0; i < 6; i++) {
        printf("%d ", 1 + (rand() %45));  // rand() 함수로 난수 생성
    }
    return 0;
}
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730805015744/868a2b56-977e-4cc9-95bf-c3160a6b2584.png align="center")

* **동일한 난수 생성 문제**:
    
    * 코드에서 매번 실행할 때마다 동일한 난수가 생성된다. 이는 난수를 생성할 때 **시드(seed)**가 고정되어 있기 때문이다.
        
    * **동일한 난수 문제 해결**을 위해 `srand()` 함수를 사용하여 시드를 현재 시간으로 설정해야 한다.
        

---

**<mark>💡세번째 시도: </mark> 난수를 매번 다르게 생성**하기 위해 **시드(seed)**를 설정할 것이다. 시드는 난수 생성의 시작값을 의미하며, 시드를 매번 다르게 설정해야 프로그램을 실행할 때마다 **다른 난수**가 생성되게 된다.  

**시드 설정**:

* **현재 시간을 시드로 설정**(Setting Seed with Current Time)하는 것이 가장 일반적인 방법이다. `time(NULL)` 함수는 현재 시간을 반환하며, 이를 시드로 사용하면 프로그램을 실행할 때마다 다른 난수가 생성된다.
    
* 코드에서는 `srand((unsigned)time(NULL));`를 사용하여 시드를 설정하고 있다.
    
* `#include <time.h>` 를 추가해야한다.
    

```c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define MAX 45

int main(void) {
    int i;
    srand((unsigned)time(NULL));   // 시드를 현재 시간으로 설정하여 난수를 다르게 생성
    for (i = 0; i < 6; i++) {
        printf("%d ", 1 + (rand() %MAX));   // 1부터 45 사이의 난수 출력
    }
    return 0;
}
```

* `srand((unsigned)time(NULL));`을 통해 현재 시간을 시드로 설정하면 매번 다른 난수를 생성하였다.
    
* `1 + rand() % MAX`는 **1부터 45 사이의 난수**를 생성한다.
    

* **현재 시간을 시드로 사용하는 이유**:
    
    * 현재 시간은 매초마다 변하므로, 이를 시드로 사용하면 프로그램을 재실행할 때마다 다른 시드값이 적용되어 **다른 난수 시퀀스**(Different Random Sequence)를 생성한다.
        

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730805358666/5a78e2f3-2ca9-4d47-90fa-f03999279936.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730805365940/f512ab0d-3c97-464c-a2cc-8dc5f96785ad.png align="center")

---

### 예제2 - 동전 던지기 게임(Flip the coin)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730805415980/40037041-dfb5-46c3-81ef-ee8c70bd14c6.png align="center")

* **함수 정의**:
    
    * `coin_toss` 함수가 동전 던지기 결과를 반환한다. 이 함수는 1 또는 0을 반환하여 1이면 앞면, 0이면 뒷면을 나타내는 방식으로 동작한. (실제 함수 구현이 이미지는 보이지 않지만, 보통 `rand() % 2`로 1 또는 0을 생성합니다.)
        
* **난수 생성 초기화**:
    
    * `srand((unsigned)time(NULL));`를 사용해 **시드**(Seed)를 현재 시간으로 설정합니다. 이렇게 하면 매번 프로그램을 실행할 때마다 다른 난수 시퀀스를 생성하므로, 동전 던지기 결과도 매번 다르게 나온다.
        
* **반복문을 사용한 동전 던지기**:
    
    * `for` 반복문을 사용하여 100번 동전을 던집니다. 각 반복에서 `coin_toss()`를 호출해 결과가 1이면 `heads`(앞면)를 증가시키고, 그렇지 않으면 `tails`(뒷면)를 증가시킨다.
        
* **결과 출력**:
    
    * 100번의 던지기가 끝나면 앞면과 뒷면이 나온 횟수를 화면에 출력한다.
        
    

```c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int coin_toss(void) {
    return rand() % 2;  // 1이면 앞면, 0이면 뒷면
}

int main(void) {
    int toss;
    int heads = 0;
    int tails = 0;
    srand((unsigned)time(NULL));  // 시드 설정

    for (toss = 0; toss < 100; toss++) {
        if (coin_toss() == 1)
            heads++;
        else
            tails++;
    }

    printf("동전의 앞면: %d\n", heads);
    printf("동전의 뒷면: %d\n", tails);

    return 0;
}
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730805799462/6a65dcd0-6085-4388-971c-65783cbd47bd.png align="center")

* `srand((unsigned)time(NULL));`를 사용해 **시드를 현재 시간**으로 설정하여 매번 다른 난수를 생성하였다.
    
* `coin_toss()` 함수는 동전 던지기를 시뮬레이션하여 1(앞면) 또는 0(뒷면)을 반환한다.
    
* 100번 던진 결과로 앞면과 뒷면이 나온 횟수를 화면에 출력한다. 이 숫자는 매번 바뀐다.
    

---

### 예제3- 자동차 경주 게임 (Car Speed Game)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730805876517/281fcf4e-bbca-4305-948d-8a3eaca4c756.png align="center")

* **난수 초기화**:
    
    * 경주를 시작하기 전에 난수를 설정한다. `srand((unsigned)time(NULL));`와 같은 방식으로 시드를 설정하면, 프로그램이 매번 실행될 때마다 다른 결과를 얻을 수 있다.
        
* **자동차 이동 거리 결정**:
    
    * `for` 반복문을 사용하여 각 자동차의 이동을 반복한다.
        
    * 각 반복에서 `rand()` 함수를 통해 난수를 생성하여 각 자동차의 이동 거리에 누적한다.
        
* **자동차 출력 함수** `disp_car`:
    
    * `disp_car` 함수는 자동차 번호와 이동한 거리에 따라 화면에 자동차의 위치를 표시한다.
        
    * `distance/10`만큼 `*`을 출력하여 자동차가 이동한 거리를 시각적으로 보여준다.
        

```c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void disp_car(int car_number, int distance) {
    int i;
    printf("CAR #%d: ", car_number);
    for (i = 0; i < distance / 10; i++) {
        printf("*");
    }
    printf("\n");
}

int main(void) {
    int car1_distance = 0;
    int car2_distance = 0;
    int i;

    srand((unsigned)time(NULL));  // 난수 초기화

    for (i = 0; i < 10; i++) {  // 10번 반복
        car1_distance += rand() % 100;  // 자동차 1의 주행 거리 증가
        car2_distance += rand() % 100;  // 자동차 2의 주행 거리 증가

        disp_car(1, car1_distance);  // 자동차 1 출력
        disp_car(2, car2_distance);  // 자동차 2 출력
    }

    return 0;
}
```

* **난수를 사용해 이동 거리**를 결정하는 자동차 경주 게임을 구현하였다.
    

* **disp\_car** 함수는 자동차 번호와 이동 거리를 바탕으로 `*`를 출력해 자동차의 진행 상황을 시각화한다.
    
* `rand()` 함수를 사용해 매번 다른 이동 거리를 설정하고, `srand((unsigned)time(NULL));`를 통해 매번 실행할 때마다 결과가 달라지도록 설정하였다.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730807344332/5fb7d2cf-b08c-4aa1-9be2-b89b2777ad23.png align="center")

---

### 예제3- 자동차 경주 게임 차3대 (3 Cars Speed Game)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730807398836/698811d5-3884-47da-9d16-140e03c5bb9a.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730807465926/66864990-282e-4471-8d2a-55219f7cd6d2.png align="center")

---

### 표준 라이브러리 - 수학 함수 (Standard Library - Mathematical Functions)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730807522911/f6a486c8-9b60-4361-9a47-8530a2a2ebf6.png align="center")

* **수학 라이브러리 함수**(Mathematical Library Functions):
    
    * **복잡한 계산**(Complex Calculations)을 할 때 **수학 함수**를 사용하면 편리하다. 이러한 함수들은 미리 정의되어 있어, 필요한 수식을 쉽게 처리할 수 있다.
        
* **math.h 헤더 파일**:
    
    * 수학 함수들은 `math.h` 헤더 파일에 포함되어 있다. 이 파일을 포함(`include`)하면 다양한 수학 함수를 사용할 수 있게 된다.
        
    * 예를 들어, 제곱근을 계산하는 `sqrt()` 함수, 지수를 계산하는 `pow()` 함수 등이 있다.
        
* **double 형 반환**:
    
    * 대부분의 수학 함수는 **double 형**(Double Type) 매개변수와 반환값을 가진다. 이는 수학 함수들이 일반적으로 **소수점 이하의 값**을 다루기 때문이다.
        

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730807552190/30151460-8dba-4087-a132-1fc03c732c92.png align="center")

---

### **floor() function &** **ceil() function**

**<mark>💡요약: </mark>** 이 두 함수는 소수를 처리할 때 유용하며, **소수점 이하의 값을 버리거나 올림**하는 기능을 제공한다.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730807609826/19fdbeed-7c93-403e-88c2-38539eac8555.png align="center")

* **floor() 함수**:
    
    * **floor() 함수**는 주어진 값의 소수점 이하를 버리고 **가장 가까운 작은 정수**(Nearest Lower Integer)로 내림한다.
        
    * 예를 들어, `value`가 1.6일 때, `floor(1.6)`은 1.0을 반환한다.
        
* **ceil() 함수**:
    
    * **ceil() 함수**는 주어진 값의 소수점 이하를 올리고 **가장 가까운 큰 정수**(Nearest Higher Integer)로 올림한다.
        
    * 예를 들어, `value`가 1.6일 때, `ceil(1.6)`은 2.0을 반환한다.
        

```c
#include <stdio.h>
#include <math.h>  // floor()와 ceil() 함수를 사용하기 위한 헤더 파일

int main() {
    double result, value = 1.6;

    result = floor(value);   // result는 1.0이다.
    printf("%lf\n", result);

    result = ceil(value);    // result는 2.0이다.
    printf("%lf\n", result);

    return 0;
}
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730808052209/b5800cc3-aa52-455f-a992-717788af9aa9.png align="center")

* **헤더 파일 추가**:
    
    * `#include <math.h>`: `floor()`와 `ceil()` 함수를 사용하기 위해 `math.h` 헤더 파일을 추가하였다.
        
* **main() 함수 안에 코드 넣기**:
    
    * C 언어에서는 모든 실행 코드는 반드시 `main()` 함수와 같은 함수 안에 있어야 한다. 그래서 `result = floor(value);`와 `result = ceil(value);` 코드를 `main()` 함수 안에 넣었다.
        

---

### fabs() function

* **fabs() 함수**는 주어진 **실수의 절대값**(Absolute Value)을 반환한다. 절대값은 숫자의 부호를 제거한 값이다.
    
* 예를 들어, `12.0`과 `-12.0`의 절대값은 모두 `12.0`이다.
    

**예제**:

```c
#include <stdio.h>
#include <math.h>  

int main(void) {
printf("12.0의 절대값은 %f\n", fabs(12.0));
printf("-12.0의 절대값은 %f\n", fabs(-12.0));

return 0;
}
```

* * 이 코드에서는 `fabs(12.0)`과 `fabs(-12.0)`의 결과를 출력한다.
        
    * `fabs(12.0)`은 `12.0`을 반환하고, `fabs(-12.0)`도 `12.0`을 반환한다.
        
    * `fabs()` 함수는 `math.h` 헤더 파일에 포함되어 있다.
        

---

### pow() & sqrt()

두 함수는 각각 거듭제곱과 제곱근을 계산할 때 사용된다.

* **pow() 함수**:
    
    * **pow() 함수**는 주어진 숫자의 **거듭제곱**(Exponentiation)을 계산한다.
        
    * 예를 들어, `pow(10.0, 3.0)`은 10의 3제곱을 계산하여 1000을 반환한다.
        
    * 이 함수는 첫 번째 인수로 **밑**(base), 두 번째 인수로 **지수**(exponent)를 받는다.
        
* **sqrt() 함수**:
    
    * **sqrt() 함수**는 주어진 숫자의 **제곱근**(Square Root)을 계산한다.
        
    * 예를 들어, `sqrt(16)`은 16의 제곱근을 계산하여 4를 반환한다.
        

```c
#include <stdio.h>
#include <math.h>  

int main(void) {
printf("10의 3승은 %.0f\n", pow(10.0, 3.0));
printf("16의 제곱근은 %.0f\n", sqrt(16));

return 0;
}
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730809010366/6373c07b-fd18-43ac-952c-26ac73b779bf.png align="center")

---

### **삼각 함수**(Trigonometric Functions)- `cos()`, `sin()`, `tan()`

위의 함수들은 각도를 입력으로 받아 **코사인, 사인, 탄젠트 값**을 계산한다.  

* **math.h 헤더 파일 포함**:
    
    * `math.h` 헤더 파일에는 다양한 수학 함수들이 포함되어 있으며, 삼각 함수인 `sin()`, `cos()`, `tan()`도 이 파일에 정의되어 있다.
        
    * **math.h**를 포함하면 다양한 수학 함수들을 사용할 수 있게 된다.
        
* **sin(), cos(), tan() 함수**:
    
    * `sin(double x)`: 주어진 각도의 **사인 값**(Sine Value)을 계산한다.
        
    * `cos(double x)`: 주어진 각도의 **코사인 값**(Cosine Value)을 계산한다.
        
    * `tan(double x)`: 주어진 각도의 **탄젠트 값**(Tangent Value)을 계산한다.
        
    * 이 함수들은 각도를 **라디안 값**으로 받아서 계산을 수행한다.
        

```c
#include <math.h>
#include <stdio.h>

int main(void) {
    double pi = 3.1415926535;
    double x, y;

    x = pi / 2;          // 90도에 해당하는 라디안 값
    y = sin(x);          // sin(90도) 계산
    printf("sin( %f ) = %f\n", x, y);

    y = cos(x);          // cos(90도) 계산
    printf("cos( %f ) = %f\n", x, y);

    return 0;
}
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730809151788/bc452206-1dc6-45cc-aaec-d07e772d808d.png align="center")

* 여기서 `x`를 `pi / 2`로 설정하여 90도에 해당하는 라디안 값으로 설정한다.
    
* `sin(x)`는 1을 반환하고, `cos(x)`는 0을 반환한다.
    
* `sin(1.570796) = 1.000000`과 `cos(1.570796) = 0.000000`이 출력되다.
    

---

### `exit()`, `system()`, `time()` Function

* **exit() 함수**:
    
    * **exit() 함수**는 프로그램을 즉시 종료할 때 사용한다. 이 함수가 호출되면, 이후의 코드는 실행되지 않고 프로그램이 종료되게 된다.
        
* **system() 함수**:
    
    * **system() 함수**는 운영 체제 명령을 실행할 수 있게 한다.
        
    * 예를 들어, `system("dir");`는 현재 디렉토리의 파일 목록을 출력하고, `system("cls");`는 콘솔 화면을 지운다.
        
    * 이 함수를 통해 DOS 명령어(`DIR`, `COPY`, `DEL`, `MKDIR` 등)를 직접 실행할 수 있다.
        
* **time(NULL) 함수**:
    
    * **time(NULL)**은 현재 시간을 반환한다.
        
    * 반환된 값은 1970년 1월 1일부터 현재까지의 초 단위 시간이니다.
        
    * 이 값은 주로 난수의 시드값을 설정하거나 시간 관련 계산에 사용된다.
        

```c
#include <stdlib.h>
#include <stdio.h>

int main(void) {
    system("dir");  // 현재 디렉토리 목록을 출력
    printf("아무 키나 치세요\n");
    getchar();      // 키 입력 대기
    system("cls");  // 화면을 지움

    return 0;
}
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730809349744/74dba135-4491-48c4-a31a-63f47ea950bb.png align="center")

* `system("dir");` 명령을 통해 현재 디렉토리의 파일 목록이 출력된다.
    
* `printf("아무 키나 치세요\n");`로 메시지를 출력하고 `getchar()`로 키 입력을 기다린다.
    
* 사용자가 키를 입력하면 `system("cls");`로 화면이 지워진다.
    

---

### **함수를 사용하는 이유**

**<mark>💡요약:</mark>** **함수는 코드 중복을 줄이고**(Reduce Code Duplication), **다른 프로그램에서도 재사용 가능**(Reusable in Other Programs)하며, 복잡한 문제를 단순하게 나누어 해결하는 데 도움을 준다.

* **소스 코드의 중복성을 없애준다**:
    
    * 함수를 사용하면 동일한 작업을 여러 번 반복해서 작성할 필요 없이, 함수를 호출하여 간단히 처리할 수 있다.
        
    * 이로 인해 **코드가 더 간결**해지고 **유지보수가 용이**해진다.
        
* **재사용 가능**:
    
    * 한 번 작성된 함수는 다른 프로그램에서도 재사용할 수 있다. 이를 통해 코드 작성 시간을 절약하고 일관성을 유지할 수 있게된다.
        
    * 예를 들어, 수학 계산을 위한 함수나 데이터 처리를 위한 함수는 여러 프로그램에서 재사용할 수 있다.
        
* **복잡한 문제를 단순한 부분으로 분해**:
    
    * 함수를 사용하면 **복잡한 문제**를 여러 **작은 부분**으로 나눌 수 있다. 각각의 함수가 작은 단위의 작업을 수행하도록 설계하면, 전체 프로그램 구조를 이해하고 관리하기가 쉬워진다.
        
    * 예를 들어, 큰 계산을 여러 단계로 나누고 각 단계를 함수로 작성할 수 있다.
        
    
    ---
    
    ### 복잡한 프로그램을 함수로 분리한다.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730809483563/5a44abaf-acaf-4853-ac1e-d587ffccc135.png align="center")

* **복잡한 코드의 문제**:
    
    * 처음의 `main` 함수는 하나의 긴 코드로 작성되어 있다. 리스트를 읽어오고, 정렬하고, 출력하는 각 기능이 모두 `main` 함수 안에 있다.
        
    * 코드가 복잡하게 얽혀 있어서, 프로그램이 어떤 작업을 수행하는지 파악하기 어렵고 유지보수가 어렵게 된다.
        
* **함수로 분리하여 단순화**:
    
    * `main` 함수에서 각 작업을 별도의 함수로 분리하여 단순하게 만들 수 있다.
        
    * `read_list()`: 리스트를 읽어오는 함수
        
    * `sort_list()`: 리스트를 정렬하는 함수
        
    * `print_list()`: 정렬된 리스트를 출력하는 함수
        
* **함수로 분리한 코드의 장점**:
    
    * 각 함수가 한 가지 작업만 담당하기 때문에 **코드의 가독성**(Readability)이 높아진다.
        
    * 특정 기능을 수정하거나 개선할 때 그 함수만 수정하면 되므로 **유지보수**(Maintainability)가 용이해진다.
        
    * `main` 함수가 더 간결해져 프로그램의 흐름을 쉽게 이해할 수 있다.
        

---

### **모듈화**(Modularization)

**<mark>💡요약</mark>**: 모듈화는 큰 프로그램을 여러 개의 **모듈**(Modules)로 나누어 구성하는 방법으로, 각 모듈이 독립적으로 동작하고 **상호 작용**을 최소화하도록 설계하는 것이 목표로 한다.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730809535353/dcc09911-2aa5-4108-935f-d50331e459e3.png align="center")

* **좋은 모듈화**:
    
    * 좋은 모듈화에서는 모듈 간의 **상호 작용이 최소화**(Minimal Interaction Between Modules)된다.
        
    * 예를 들어, **모듈 1**은 **모듈 2**와만 상호 작용하고, **모듈 3**과는 간접적으로 연결된다. 이렇게 하면 모듈 간의 연결이 단순해져서 프로그램을 이해하고 유지보수하기가 쉬워진다.
        
* **나쁜 모듈화**:
    
    * 나쁜 모듈화에서는 모듈 간의 **상호 작용이 복잡**(Complex Interaction Between Modules)해진다.
        
    * 예를 들어, **모듈 1**과 **모듈 2**가 서로 여러 번 연결되어 있고, **모듈 3**과도 여러 관계가 얽혀 있다. 이렇게 되면 모듈 간의 의존성이 높아져서 코드 수정 시 에러가 발생할 가능성이 높아지고 유지보수가 어려워지게 된다.
        
* **좋은 모듈화의 장점**:
    
    * 모듈 간의 연결이 단순할수록 각 모듈이 독립적으로 기능을 수행하기 쉬워진다.
        
    * 코드 수정이나 기능 확장이 필요한 경우, 해당 모듈만 수정하면 되므로 **유지보수가 용이**(Ease of Maintenance)하다.
        

---
