[코딩도장] Unit 60 ~ 62
1. 함수
1. 함수 정의하기
함수를 정의하는 방법은 반환값 자료형, 함수 이름, ( ) 순으로 적어준 뒤
{ } 안에 원하는 코드를 작성하면 된다
함수는 main 함수 바깥에서 작성해야 한다
void hello() // 반환값이 없는 hello 함수 정의
{
printf("Hello, world!\n"); // Hello, world! 출력
}
함수의 반환값 자료형 부분에 void 를 적어주면 함수의 반환값이 없다는 뜻이 된다
int main()
{
hello(); // hello 함수 호출
return 0;
}
main 함수 안에서 함수이름을 적어준 뒤 ( ) 를 붙이면 함수를 사용할 수 있다
이렇게 함수를 사용하는 방법을
함수를 호출(call) 한다 라고 부른다
main 함수와 hello 함수의 실행순서는 아래 그림과 같다
함수 안에 선언된 변수는 지역 변수라고 한다
※ 지역 변수는 함수가 끝나면 사라지기 때문에 함수 바깥에선 사용할 수 없다
2. 함수 선언과 정의 분리하기
C언어는 함수를 선언하고 정의할 수 있다
함수 형태만 선언하기에 함수 원형이라 부른다
void hello(); // 반환값이 없는 hello 함수 원형 선언
int main()
{
hello(); // hello 함수 호출
return 0;
}
void hello() // 반환값이 없는 hello 함수 정의
{
printf("Hello, world!\n"); // Hello, world! 출력
}
main 함수 위에 함수 선언을 먼저 한 뒤
main 함수 아래에 hello 함수를 정의해주면 된다.
※ 함수 선언만 있고 정의가 없다면 링크 에러가 발생한다
2. 함수에서 반환값 사용하기
1. 정수, 실수, 불 반환하기
반환값은 함수를 정의할 때 반환값의 자료형을 지정하고
함수 안에서 return 으로 반환하면 된다
반환값자료형 함수이름()
{
return 반환값;
}
※ 반환값과 반환값 자료형이 일치해야 한다
int one() // 반환값이 int형인 one 함수 정의
{
return 1; // 1을 반환
}
int main()
{
int num1;
num1 = one(); // int형을 반환했으므로 int형 변수에 저장
printf("%d\n", num1); // 1
return 0;
}
반환값을 저장하려면 반환값을 저장할 변수에
할당 연산자를 사용한 뒤 함수를 호출해주면 된다
반환값이 변수에 저장되는 과정은 다음과 같다
반환값을 변수에 저장하지 않고 바로 사용하려면 printf 안에 넣어서 실행해도 된다
printf("%d\n", one()); // one 함수의 반환값을 바로 사용
실수, 불 자료형도 마찬가지로
반환값 자료형을 float, bool 로 설정한 뒤
return 으로 float, bool 값을 반환하면 된다
2. 포인터 반환하기
포인터를 반환하려면 반환값 자료형과 함수 이름 사이에 * 를 붙여주면 된다
반환값자료형 *함수이름()
{
return 반환값;
}
지역 변수는 함수가 끝나면 사라지기 때문에
함수의 반환값으로 사용할 수 없다
포인터를 반환하려면 malloc 함수로 메모리를 할당한 뒤 반환해야 한다
int *ten() // int 포인터를 반환하는 ten 함수 정의
{
int *numPtr = malloc(sizeof(int)); // int 크기만큼 동적 메모리 할당
*numPtr = 10; // 역참조로 10 저장
return numPtr; // 포인터 반환. malloc으로 메모리를 할당하면 함수가 끝나도 사라지지 않음
}
int main()
{
int* numPtr;
numPtr = ten(); // 함수를 호출하고 반환값을 numPtr에 저장
printf("%d\n", *numPtr); // 10: 메모리를 해제하기 전까지 안전함
free(numPtr); // 다른 함수에서 할당한 메모리라도 반드시 해제해야 함
return 0;
}
다른 함수에서 할당한 메모리라 하더라도 해제하기 전까지는 그대로 사용할 수 있다
※ 메모리가 main 이 아닌 다른 함수에서 할당되었다 하더라도 free 함수로 해제해준다
3. void 포인터 반환하기
void 포인터를 활용하면 어떤 자료형으로 된 포인터도 넣을 수 있다
void *allocMemory() // void 포인터를 반환하는 allocMemory 함수 정의
{
void *ptr = malloc(100); // 100바이트만큼 동적 메모리 할당
return ptr; // void 포인터 반환
}
int main()
{
char *s1 = allocMemory(); // void 포인터를 char 포인터에 넣어서 문자열처럼 사용
strcpy(s1, "Hello, world!"); // s1에 Hello, world! 복사
printf("%s\n", s1); // Hello, world!
free(s1); // 동적 메모리 해제
int *numPtr1 = allocMemory(); // void 포인터를 int 포인터에 넣어서 정수 배열처럼 사용
numPtr1[0] = 10; // 첫 번째 요소에 10 저장
numPtr1[1] = 20; // 두 번째 요소에 20 저장
printf("%d %d\n", numPtr1[0], numPtr1[1]); // 10 20
free(numPtr1); // 동적 메모리 해제
return 0;
}
void *allocMemory 와 같이 반환값 자료형을 void 포인터로 지정한다
함수 안에서는 void 포인터에 malloc 으로 100바이트만큼 메모리를 할당한 뒤 반환한다
main 함수에서는 allocMemory 함수 안에서 malloc 을 사용하고 있으므로
allocMemory 에서 반환된 포인터를 사용할 때마다 free 함수로 메모리를 해제해줘야 한다
void *allocMemory()
{
return malloc(100); // malloc 함수를 호출하면서 바로 반환
}
ptr 변수를 선언하지 않고, malloc 함수를 호출하면서 바로 반환하면
코드를 줄일 수 있다
4. 구조체, 구조체 포인터 반환하기
C언어는 구조체를 반환하여 데이터를 묶어서 한번에 가져올 수 있다
struct 구조체이름 함수이름()
{
return 구조체변수;
}
구조체를 반환하는 함수를 정의하려면
struct 키워드와 구조체 이름을 함수 이름 앞에 붙여주면 된다
struct Person {
char name[20];
int age;
char address[100];
};
struct Person getPerson() // Person 구조체를 반환하는 getPerson 함수 정의
{
struct Person p;
strcpy(p.name, "홍길동");
p.age = 30;
strcpy(p.address, "서울시 용산구 한남동");
return p; // 구조체 변수 반환
}
함수 안에서 Person 구조체 변수를 선언하고 값을 저장한 뒤 반환한다
int main()
{
struct Person p1;
p1 = getPerson(); // 반환된 구조체 변수의 내용이 p1로 모두 복사됨
// getPerson에서 저장한 값들이 출력됨
printf("이름: %s\n", p1.name); // 홍길동
printf("나이: %d\n", p1.age); // 30
printf("주소: %s\n", p1.address); // 서울시 용산구 한남동
return 0;
}
구조체 변수를 반환한 뒤 다른 변수에 저장하면
반환된 구조체의 내용을 모두 복사하게 된다
→ 복사할 공간이 더 필요하게 되어 공간이 낭비된다
구조체를 반환할 때는 구조체 복사가 일어나지 않도록
malloc 함수로 메모리를 할당한 뒤 구조체 포인터를 반환하는 것이 좋다
구조체 포인터를 반환하는 함수는
구조체 이름과 함수 이름 사이에 * 를 붙이면 된다
struct 구조체이름 *함수이름()
{
return 구조체포인터;
}
struct Person *allocPerson() // Person 구조체 포인터를 반환하는 allocPerson 함수 정의
{
struct Person *p = malloc(sizeof(struct Person)); // 구조체 포인터에 동적 메모리 할당;
strcpy(p->name, "홍길동");
p->age = 30;
strcpy(p->address, "서울시 용산구 한남동");
return p; // 구조체 포인터 반환
}
함수 안에서 구조체 포인터에 메모리를 할당하고 값을 저장한 뒤
구조체 포인터를 반환한다
int main()
{
struct Person *p1;
p1 = allocPerson(); // 포인터를 반환하여 p1에 메모리 주소 저장
// allocPerson에서 저장한 값들이 출력됨
printf("이름: %s\n", p1->name); // 이름: 홍길동
printf("나이: %d\n", p1->age); // 나이: 30
printf("주소: %s\n", p1->address); // 주소: 서울시 용산구 한남동
free(p1); // 동적 메모리 해제
return 0;
}
main 함수에서 allocPerson 함수를 호출한 뒤 반한된 포인터를 p1 에 저장한다
구조체 포인터이므로 -> (화살표 연산자)를 이용하여 멤버에 접근한다
메모리 사용이 끝났다면 free 함수로 해제해준다
주소가 들어있는 포인터만 반환하여 사용하므로
구조체의 내용을 복사하지 않아 효율적이다
typedef struct _Person {
char name[20];
int age;
char address[100];
} Person, *PPerson; // 구조체 별칭 Person, 구조체 포인터 별칭 PPerson
구조체 포인터 별칭을 정의했다면
함수의 반환값 자료형에 구조체 포인터 별칭을 그대로 지정하면 된다
※ 공용체와 열거형도 반환할 수 있다
3. 함수에서 매개변수 사용하기
1. 매개변수 사용하기
매개변수를 사용하려면 함수를 정의할 때 ( ) 안에 자료형과 변수 이름을 지정하면 된다
void helloNumber(int num1) // 반환값 없음, int형 매개변수 한 개 지정
{
printf("Hello, %d\n", num1); // Hello, 와 매개변수를 조합하여 문자열 출력
}
함수를 정의할 때 int num1 과 같이 매개변수를 지정한다
※ 매개변수를 여러개 사용하려면 각 매개변수를 , (콤마) 로 구분한다
매개변수, 파라미터(parameter), 형식 매개변수(formal parameter), 인자
→ 함수 바깥에서 전달된 값이 저장되는 변수
// 매개변수
// ↓ ↓
int add(int a, int b)
{
return a + b;
}
인수, 전달인자, 아규먼트(argument), 실행 전달인자(actual argument)
→ 함수를 호출할 때 전달하는 값이나 변수
// 인수
// ↓ ↓
add(10, 20);
같은 변수나 값을 가리키지만
함수를 기준으로 봤을 때 용어가 다른 것이다
4. 심사문제
60.7 함수 정의하기
다음 소스 코드를 완성하여 "192.168.10.5" 와 "Jupiter" 가 각 줄에 출력되게 만드세요.
정답에는 밑줄 친 부분에 들어갈 코드만 작성해야 합니다.
#include <stdio.h>
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
__________________________
int main()
{
printIPAddress();
printHostname();
return 0;
}
정답
void printIPAddress() {
printf("192.168.10.5\n");
}
void printHostname() {
printf("Jupiter\n");
}
60.8 함수 선언하기
다음 소스 코드를 완성하여 "Beethoven"과 "9th Symphony"가 각 줄에 출력되게 만드세요.
정답에는 밑줄 친 부분에 들어갈 코드만 작성해야 합니다.
#include <stdio.h>
___________________
___________________
int main()
{
printName();
printOrdinal();
return 0;
}
void printName()
{
printf("Beethoven\n");
}
void printOrdinal()
{
printf("9th Symphony\n");
}
정답
void printName();
void printOrdinal();
61.10 게임 캐릭터 능력치 함수 만들기
다음 소스 코드를 완성하여 20.500000, "false"가 각 줄에 출력되게 만드세요.
정답에는 밑줄 친 부분에 들어갈 코드만 작성해야 합니다.
#include <stdio.h>
#include <stdbool.h>
____________________
____________________
____________________
____________________
____________________
____________________
____________________
____________________
int main()
{
float armor;
bool slow;
armor = getArmor();
slow = hasSlowSkill();
printf("%f\n", armor);
printf("%s\n", slow == true ? "true" : "false");
return 0;
}
정답
float getArmor() {
return 20.5;
}
bool hasSlowSkill() {
return false;
}
61.11 문자열 포인터 반환하기
다음 소스 코드를 완성하여 "Neptune"이 출력되게 만드세요.
정답에는 밑줄 친 부분에 들어갈 코드만 작성해야 합니다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
_____________________
_____________________
_____________________
_____________________
_____________________
_____________________
int main()
{
char *name;
name = getName();
printf("%s\n", name);
free(name);
return 0;
}
정답
void *getName() {
char * str = malloc(sizeof(char) * 100);
strcpy(str, "Neptune");
return str;
}
61.12 메모리 할당 함수 만들기
다음 소스 코드를 완성하여 "Mercury"와 87.969002 11.5877602가 각 줄에 출력되게 만드세요.
정답에는 밑줄 친 부분에 들어갈 코드만 작성해야 합니다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
___________________
___________________
___________________
___________________
___________________
int main()
{
char *name;
float *stats;
name = allocMemory();
strcpy(name, "Mercury");
printf("%s\n", name);
free(name);
stats = allocMemory();
stats[0] = 87.969f;
stats[1] = 115.8776f;
printf("%f %f\n", stats[0], stats[1]);
free(stats);
return 0;
}
정답
void *allocMemory() {
void *ptr = malloc(100);
return ptr;
}
61.13 2차원 정보 만들기
다음 소스 코드를 완성하여 90 75 가 출력되게 만드세요.
정답에는 밑줄 친 부분에 들어갈 코드만 작성해야 합니다.
#include <stdio.h>
#include <stdlib.h>
struct Point2D {
int x;
int y;
};
______________________________
______________________________
______________________________
______________________________
______________________________
______________________________
______________________________
int main()
{
struct Point2D *pos1;
pos1 = allocPoint2D();
printf("%d %d\n", pos1->x, pos1->y);
free(pos1);
return 0;
}
정답
struct Point2D *allocPoint2D() {
struct Point2D * pos = malloc(sizeof(struct Point2D));
pos->x = 90;
pos->y = 75;
return pos;
}
62.7 게임 캐릭터 능력치 설정 함수 만들기
다음 소스 코드를 완성하여 공격 속도가 각 줄에 출력되게 만드세요.
정답에는 밑줄 친 부분에 들어갈 코드만 작성해야 합니다.
#include <stdio.h>
__________________
__________________
__________________
__________________
int main()
{
setAttackSpeed(0.638f);
setAttackSpeed(1.23f);
return 0;
}
정답
void setAttackSpeed(float a) {
printf("Attack Speed: %f\n", a);
}
62.8 덧셈 함수 만들기
표준 입력으로 두 정수가 입력됩니다(입력 값의 범위는 long long의 범위와 같음.) 다음 소스 코드를 완성하여 두 정수의 합이 출력되게 만드세요.
정답에는 밑줄 친 부분에 들어갈 코드만 작성해야 합니다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
____________________
____________________
____________________
____________________
int main()
{
long long num1, num2;
scanf("%lld %lld", &num1, &num2);
printf("%lld\n", add(num1, num2));
return 0;
}
정답
long long add(long long a, long long b) {
return a + b;
}
62.9 3차원 정보 만들기
표준 입력으로 x, y, z 좌표가 입력됩니다. 다음 소스 코드를 완성하여 입력된 x, y, z 좌표가 출력되게 만드세요.
정답에는 밑줄 친 부분에 들어갈 코드만 작성해야 합니다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
struct Point3D {
float x;
float y;
float z;
};
_______________________________________________________
_______________________________________________________
_______________________________________________________
_______________
_______________
_______________
_______________
_______________
int main()
{
float x, y, z;
struct Point3D *pos1;
scanf("%f %f %f", &x, &y, &z);
pos1 = allocPoint3D(x, y, z);
printf("%f %f %f\n", pos1->x, pos1->y, pos1->z);
free(pos1);
return 0;
}
정답
void *allocPoint3D(float a, float b, float c) {
struct Point3D *p = malloc(sizeof(struct Point3D));
p->x = a;
p->y = b;
p->z = c;
return p;
}
'Coding > C' 카테고리의 다른 글
[C언어] 함수 가변인자, 재귀호출 - 코딩도장 (0) | 2024.02.10 |
---|---|
[C언어] 함수에서 매개변수 사용하기(포인터, 배열, 구조체) - 코딩도장 (0) | 2024.02.06 |
[C언어] 자료형 변환, 포인터 연산 - 코딩도장 (0) | 2024.01.30 |
[C언어] 열거형 - 코딩도장 (0) | 2024.01.27 |
[C언어] 공용체, 구조체 & 공용체 활용 - 코딩도장 (0) | 2024.01.24 |