소개
이 랩에서는 C++ 의 함수에 대해 배우게 됩니다. 함수를 정의하고 호출하는 방법, 그리고 함수에 인수를 전달하는 방법을 배우게 됩니다.
이 랩에서는 C++ 의 함수에 대해 배우게 됩니다. 함수를 정의하고 호출하는 방법, 그리고 함수에 인수를 전달하는 방법을 배우게 됩니다.
때때로, 코드의 특정 부분이 여러 번 사용되어야 합니다. 유지 관리 및 이해의 용이성을 위해, 해당 코드를 "서브루틴" - 함수에 넣고 이 함수를 여러 번 "호출"하는 것이 좋습니다.
함수를 사용하는 데는 두 당사자가 관련됩니다: 함수를 호출하는 호출자 (caller) 와 호출되는 함수 (function) 입니다. 호출자는 함수에 인수 (argument(s)) 를 전달합니다. 함수는 이러한 인수 (들) 를 받아 함수 본문 내에서 프로그래밍된 작업을 수행하고, 결과의 일부를 호출자에게 다시 반환합니다.
원의 면적을 여러 번 계산해야 한다고 가정해 봅시다. getArea()라는 함수를 작성하고 필요할 때 재사용하는 것이 좋습니다.
/* Test Function */
#include <iostream>
using namespace std;
const int PI = 3.14159265;
// Function Prototype (함수 선언)
double getArea(double radius);
int main() {
double radius1 = 1.1, area1, area2;
// call function getArea()
area1 = getArea(radius1);
cout << "area 1 is " << area1 << endl;
// call function getArea()
area2 = getArea(2.2);
cout << "area 2 is " << area2 << endl;
// call function getArea()
cout << "area 3 is " << getArea(3.3) << endl;
}
// Function Definition
// Return the area of a circle given its radius
double getArea(double radius) {
return radius * radius * PI;
}
출력:
area 1 is 3.63
area 2 is 14.52
area 3 is 32.67


C++ 에서는 함수를 사용하기 전에 함수 프로토타입을 선언하고, 프로그래밍된 연산을 포함하는 본문과 함께 함수 정의를 제공해야 합니다.
함수 정의의 구문은 다음과 같습니다.
returnValueType functionName ( parameterList ) {
functionBody ;
}
함수 프로토타입은 컴파일러에게 함수의 인터페이스, 즉 반환 유형, 함수 이름 및 매개변수 유형 목록 (매개변수의 수와 유형) 을 알려줍니다. 이제 함수는 파일의 어느 곳에서나 정의할 수 있습니다. 예를 들어,
// Function prototype - placed before the function is used.
double getArea(double); // without the parameter name
double getArea(double radius); // parameter names are ignored, but serve as documentation
"void" 반환 유형
호출자에게 값을 반환할 필요가 없으면 반환 값 유형을 void로 선언할 수 있습니다. 함수의 본문에서 반환 값 없이 "return;" 문을 사용하여 호출자에게 제어를 반환할 수 있습니다.
실제 매개변수 vs. 형식 매개변수
위의 예에서 getArea(double radius)의 시그니처에 선언된 변수 (double radius)는 형식 매개변수 (formal parameter) 로 알려져 있습니다. 그 범위는 함수의 본문 내에 있습니다. 함수가 호출자에 의해 호출될 때, 호출자는 소위 실제 매개변수 (actual parameter) (또는 인수 (arguments)) 를 제공해야 하며, 그 값은 실제 계산에 사용됩니다. 예를 들어, 함수가 "area1 = getArea(radius1)"을 통해 호출될 때, radius1은 실제 매개변수이며 값은 1.1입니다.
함수의 지역 변수 및 매개변수의 범위
함수 내에서 선언된 함수 매개변수를 포함한 모든 변수는 해당 함수에만 사용할 수 있습니다. 함수가 호출될 때 생성되고 함수가 반환된 후 해제 (파괴) 됩니다. 이러한 변수는 함수에 로컬하고 함수 외부에서 사용할 수 없기 때문에 지역 변수 (local variables) 라고 합니다.
C++ 는 함수에 소위 기본 인수 (default arguments) 를 도입합니다. 호출자가 함수를 호출할 때 해당 실제 인수를 생략하면 이러한 기본값이 사용됩니다. 기본 인수는 함수 프로토타입에서 지정되며 함수 정의에서 반복될 수 없습니다. 기본 인수는 위치를 기준으로 해석됩니다. 따라서 모호성을 피하기 위해 후행 (trailing) 인수를 대체하는 데만 사용할 수 있습니다. 예를 들어,
/* Test Function default arguments */
#include <iostream>
using namespace std;
// Function prototype - Specify the default arguments here
int fun1(int = 1, int = 2, int = 3);
int fun2(int, int, int = 3);
int main() {
cout << fun1(4, 5, 6) << endl; // No default
cout << fun1(4, 5) << endl; // 4, 5, 3(default)
cout << fun1(4) << endl; // 4, 2(default), 3(default)
cout << fun1() << endl; // 1(default), 2(default), 3(default)
cout << fun2(4, 5, 6) << endl; // No default
cout << fun2(4, 5) << endl; // 4, 5, 3(default)
// cout << fun2(4) << endl;
// error: too few arguments to function 'int fun2(int, int, int)'
}
int fun1(int n1, int n2, int n3) {
// cannot repeat default arguments in function definition
return n1 + n2 + n3;
}
int fun2(int n1, int n2, int n3) {
return n1 + n2 + n3;
}
출력:
15
12
9
6
15
12

C++ 는 함수 오버로딩 (function overloading) (또는 함수 다형성 (function polymorphism)) 을 도입하여, 매개변수 목록 (매개변수의 수, 유형 또는 순서) 에 따라 구분되는 동일한 함수 이름의 여러 버전을 가질 수 있도록 합니다. 오버로딩된 함수는 반환 유형으로 구분할 수 없습니다 (컴파일 오류). 호출자의 인수 목록과 일치하는 버전이 실행을 위해 선택됩니다. 예를 들어,
/* Test Function Overloading */
#include <iostream>
using namespace std;
void fun(int, int, int); // Version 1
void fun(double, int); // Version 2
void fun(int, double); // Version 3
int main() {
fun(1, 2, 3); // version 1
fun(1.0, 2); // version 2
fun(1, 2.0); // version 3
fun(1.1, 2, 3); // version 1 - double 1.1 casted to int 1 (without warning)
// fun(1, 2, 3, 4);
// error: no matching function for call to 'fun(int, int, int, int)'
// fun(1, 2);
// error: call of overloaded 'fun(int, int)' is ambiguous
// note: candidates are:
// void fun(double, int)
// void fun(int, double)
// fun(1.0, 2.0);
// error: call of overloaded 'fun(double, double)' is ambiguous
}
void fun(int n1, int n2, int n3) { // version 1
cout << "version 1" << endl;
}
void fun(double n1, int n2) { // version 2
cout << "version 2" << endl;
}
void fun(int n1, double n2) { // version 3
cout << "version 3" << endl;
}
출력:
version 1
version 2
version 3
version 1

함수에 배열을 전달할 수도 있습니다. 그러나 배열의 크기도 함수에 전달해야 합니다. 이는 호출된 함수 내의 배열 인수를 통해 배열의 크기를 알 수 있는 방법이 없기 때문입니다. 예를 들어,
/* Function to compute the sum of an array */
#include <iostream>
using namespace std;
// Function prototype
int sum(int array[], int size); // Need to pass the array size too
void print(int array[], int size);
// Test Driver
int main() {
int a1[] = {8, 4, 5, 3, 2};
print(a1, 5); // {8,4,5,3,2}
cout << "sum is " << sum(a1, 5) << endl; // sum is 22
}
// Function definition
// Return the sum of the given array
int sum(int array[], int size) {
int sum = 0;
for (int i = 0; i < size; ++i) {
sum += array[i];
}
return sum;
}
// Print the contents of the given array
void print(int array[], int size) {
cout << "{";
for (int i = 0; i < size; ++i) {
cout << array[i];
if (i < size - 1) {
cout << ",";
}
}
cout << "}" << endl;
}
출력:
{8,4,5,3,2}
sum is 22

함수에 매개변수를 전달하는 방법에는 두 가지가 있습니다: *값으로 전달 (pass by value)*과 참조로 전달 (pass by reference).
값으로 전달 (Pass-by-Value)
값으로 전달에서는 인수의 "복사본"이 생성되어 함수로 전달됩니다. 호출된 함수는 "복제본"에서 작동하며, 원본 복사본을 수정할 수 없습니다. C/C++ 에서 기본 유형 (예: int 및 double) 은 값으로 전달됩니다.
/* Fundamental types are passed by value into Function */
#include <iostream>
using namespace std;
// Function prototypes
int inc(int number);
// Test Driver
int main() {
int n = 8;
cout << "Before calling function, n is " << n << endl; // 8
int result = inc(n);
cout << "After calling function, n is " << n << endl; // 8
cout << "result is " << result << endl; // 9
}
// Function definitions
// Return number+1
int inc(int number) {
++number; // Modify parameter, no effect to caller
return number;
}
출력:
Before calling function, n is 8
After calling function, n is 8
result is 9

참조로 전달 (Pass-by-Reference)
반면에, 참조로 전달에서는 호출자의 변수에 대한 *참조 (reference)*가 함수로 전달됩니다. 즉, 호출된 함수는 동일한 데이터에서 작동합니다. 호출된 함수가 매개변수를 수정하면, 동일한 호출자의 복사본도 수정됩니다. C/C++ 에서 배열은 참조로 전달됩니다. C/C++ 는 함수가 배열을 반환하는 것을 허용하지 않습니다.
/* Function to increment each element of an array */
#include <iostream>
using namespace std;
// Function prototypes
void inc(int array[], int size);
void print(int array[], int size);
// Test Driver
int main() {
int a1[] = {8, 4, 5, 3, 2};
// Before increment
print(a1, 5); // {8,4,5,3,2}
// Do increment
inc(a1, 5); // Array is passed by reference (having side effect)
// After increment
print(a1, 5); // {9,5,6,4,3}
}
// Function definitions
// Increment each element of the given array
void inc(int array[], int size) { // array[] is not const
for (int i = 0; i < size; ++i) {
array[i]++; // side-effect
}
}
// Print the contents of the given array
void print(int array[], int size) {
cout << "{";
for (int i = 0; i < size; ++i) {
cout << array[i];
if (i < size - 1) {
cout << ",";
}
}
cout << "}" << endl;
}
출력:
{8,4,5,3,2}
{9,5,6,4,3}

참조를 전달할 때는 가능한 한 const를 사용하십시오. 이는 매개변수를 실수로 수정하는 것을 방지하고 많은 프로그래밍 오류로부터 보호합니다.
선형 검색 (linear search) 에서 검색 키는 배열의 각 요소와 선형적으로 비교됩니다. 일치하는 항목이 있으면 일치하는 요소의 인덱스를 반환하고, 그렇지 않으면 -1 을 반환합니다. 선형 검색의 복잡도는 O(n) 입니다.
/* Search an array for the given key using Linear Search */
#include <iostream>
using namespace std;
int linearSearch(const int a[], int size, int key);
int main() {
const int SIZE = 8;
int a1[SIZE] = {8, 4, 5, 3, 2, 9, 4, 1};
cout << linearSearch(a1, SIZE, 8) << endl; // 0
cout << linearSearch(a1, SIZE, 4) << endl; // 1
cout << linearSearch(a1, SIZE, 99) << endl; // 8 (not found)
}
// Search the array for the given key
// If found, return array index [0, size-1]; otherwise, return size
int linearSearch(const int a[], int size, int key) {
for (int i = 0; i < size; ++i) {
if (a[i] == key) return i;
}
// a[0] = 1;
// It will result in an error,because a[] is const, means read only
return -1;
}
출력:
0
1
-1

&로 표시되는 *참조 매개변수 (reference parameter)*를 통해 기본 유형 매개변수를 참조로 전달할 수 있습니다.
/* Test Pass-by-reference for fundamental-type parameter
via reference declaration */
#include <iostream>
using namespace std;
int squareByValue (int number); // Pass-by-value
void squareByReference (int &number); // Pass-by-reference
int main() {
int n1 = 8;
cout << "Before call, value is " << n1 << endl; // 8
cout << squareByValue(n1) << endl; // no side-effect
cout << "After call, value is " << n1 << endl; // 8
int n2 = 9;
cout << "Before call, value is " << n2 << endl; // 9
squareByReference(n2); // side-effect
cout << "After call, value is " << n2 << endl; // 81
}
// Pass parameter by value - no side effect
int squareByValue (int number) {
return number * number;
}
// Pass parameter by reference by declaring as reference (&)
// - with side effect to the caller
void squareByReference (int &number) {
number = number * number;
}
출력:
Before call, value is 8
64
After call, value is 8
Before call, value is 9
After call, value is 81

C++ 는 <cmath> 라이브러리에서 많은 일반적인 수학 함수를 제공합니다.
sin(x), cos(x), tan(x), asin(x), acos(x), atan(x):
인수 유형을 사용하고 float, double, long double 유형을 반환합니다.
sinh(x), cosh(x), tanh(x):
쌍곡선 삼각 함수.
pow(x, y), sqrt(x):
거듭제곱 및 제곱근.
ceil(x), floor(x):
부동 소수점 숫자의 천장 및 바닥 정수를 반환합니다.
fabs(x), fmod(x, y):
부동 소수점 절대값 및 모듈러스.
exp(x), log(x), log10(x):
지수 및 로그 함수.
cstdlib 헤더 (C 의 stdlib.h에서 포팅됨) 는 0 과 RAND_MAX (포함) 사이의 의사 난수 정수를 생성하는 함수 rand()를 제공합니다.
/* Test Random Number Generation */
#include <iostream>
#include <cstdlib> // for rand(), srand()
#include <ctime> // for time()
using namespace std;
int main() {
// rand() generate a random number in [0, RAND_MAX]
cout << "RAND_MAX is " << RAND_MAX << endl; // 32767
// Generate 10 pseudo-random numbers between 0 and 99
// without seeding the generator.
// You will get the same sequence, every time you run this program
for (int i = 0; i < 10; ++i) {
cout << rand() % 100 << " "; // need <cstdlib> header
}
cout << endl;
// Seed the random number generator with current time
srand(time(0)); // need <cstdlib> and <ctime> header
// Generate 10 pseudo-random numbers
// You will get different sequence on different run,
// because the current time is different
for (int i = 0; i < 10; ++i) {
cout << rand() % 100 << " "; // need <cstdlib> header
}
cout << endl;
}
출력:
RAND_MAX is 2147483647
83 86 77 15 93 35 86 92 49 21
29 0 83 60 22 55 97 80 68 87

- name: check if keyword exist
script: |
#!/bin/bash
grep -i 'rand' /home/labex/Code/test.cpp
error: Oops! We find that you didn't use "rand()" method in "test.cpp".
timeout: 3
함수를 사용하는 이점은 다음과 같습니다.