언리얼 엔진 스터디/프로그래밍: 두 판 사이의 차이
새 문서: == 기본 프로그래밍 용어 == === 변수 (Variable) === 수학의 미지수와 비슷한 개념으로, 자연수가 될 수도 소수가 될 수도 있지만 자연수로 채택된 변수는 소수가 될 수 없다. 마찬가지로 반대도 불가능하다. 이러한 변수의 등록 형식을 변수의 타입이라 부르며, 자연수와 소수를 같이 연산하려면 둘 중 하나의 타입을 바꾸어야 함 (형변환) <syntaxhighlight lang="cpp" line> // 변수... |
편집 요약 없음 |
||
12번째 줄: | 12번째 줄: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== | === 배열 (Array) === | ||
같은 타입의 | 같은 타입의 변수 및 클래스 및 구조체로 이루어진 집합. 리스트라고 생각해도 되지만 엄밀히는 다름 | ||
<syntaxhighlight lang="cpp" line> | <syntaxhighlight lang="cpp" line> | ||
#include <cstdio> | #include <cstdio> | ||
21번째 줄: | 21번째 줄: | ||
int a[2] = {-1, 1}; | int a[2] = {-1, 1}; | ||
float b[3] = {0.5f, 2.4f, 3.6f}; | float b[3] = {0.5f, 2.4f, 3.6f}; | ||
bool | bool c[4]; // 값을 초기화하지 않으면 컴파일되지 않는다. | ||
char | char d[5] = {'h', 'e', 'l', 'l', 'o'}; | ||
int e[] = {1, 2, 3, 4, 5}; // e의 길이는 자동으로 5가 된다. | |||
// 값 꺼내오기 | // 값 꺼내오기 | ||
34번째 줄: | 35번째 줄: | ||
=== 함수 (Function) === | === 함수 (Function) === | ||
작업을 수행하기 위해 설계된 코드의 | 작업을 수행하기 위해 설계된 코드의 집합으로, 아두이노에서 썼던 println, 프로세싱의 rect 등은 모두 함수이다. 함수의 목적에 따라 입력 값과 출력 값 (Return 값)이 있을 수 있다. 함수를 잘 쓰면 코드의 양이 획기적으로 줄고 가독성이 좋아짐 | ||
=== 이벤트 (Event) === | |||
* 이벤트 노드 (블루프린트) 에서 노드의 시작점 (코드의 시작) | |||
* 스크래치의 방송과 비슷하면서도 함수와도 비슷함 | |||
* 함수와의 차이점은 값을 출력 (리턴)할 수 없음 | |||
* 기본적으로 게임이 시작될 때 동작하는 이벤트 (BeginPlay)와 매 프레임마다 동작하는 이벤트 (Tick)이 있음. 이벤트를 만들 수도 있음 | |||
=== 클래스 (Class) === | |||
OOP (Object-Oriented Programming), 즉 객체지향 프로그래밍에서 사용되는 중요한 개념으로, 객체를 정의하기 위해 변수와 방법을 정의하는 템플릿이다. | |||
예시로, 사람이라는 종이 있다. 여기에는 사람의 장기, 사지 등 모든 사람들의 기본적인 공통점이 정리되어 있다. 하지만 인종, 더 나아가 개개인에 따라 세부적인 특성은 모두 다르다. 여기서 사람이라는 종은 기본적인 템플릿이고, 이 사람이라는 템플릿을 기반으로 개개인에게 차이를 두는 것이다. | |||
클래스는 세부적인 개념으로 파생될 수 있다. 위 예시로는 사람이라는 종을 프로그램에서 클래스라고 가정했을 때 사람 그 자체는 부모 클래스라고 부른다. 여기서 파생되는 황인, 백인, 흑인, 더 나아가 개개인이라는 개체로 분류되는데, 이를 자식 클래스로 비유할 수 있다. 상위 클래스의 공통점을 모두 가진 채 자식 클래스로 파생되는 것을 상속 (Inherit), 또는 확장 (Extend)라고 부른다. 상속된다고 해서 부모 클래스는 상속해준 기능을 잃는 것이 아니라 공유하는 것이다. | |||
== 프로그래밍 연산자 == | == 프로그래밍 연산자 == | ||
289번째 줄: | 292번째 줄: | ||
4 5 6 1 2 3 -2 -1 0 | 4 5 6 1 2 3 -2 -1 0 | ||
*/ | */ | ||
</syntaxhighlight> | |||
=== 클래스 === | |||
클래스는 특정 기능을 모듈화 (또는 캡슐화)하여 하나의 단위로 묶는 것을 목표로 한다. 또한, 세부적인 부분을 외부로 드러나지 않게 하여 모듈 간의 결합도를 떨어뜨린다. 이렇게 겉보기로는 불편해보이게 프로그램을 작성하는 이유는 기능이 많아졌을 때 클래스끼리 정해진 방식대로 통신하지 않으면 나중에 그 기능을 수정할 때 수많은 코드를 탐색하고 다시 작성 (리팩토링)해야 할 수 있기 떄문이다. | |||
다음은 HelloWorld라는 이름의 클래스를 만들고, NotHello라는 이름의 HelloWorld의 자식 클래스를 만드는 예제이다. | |||
<syntaxhighlight lang="cpp" line> | |||
// HelloWorld.h | |||
#include <cstdio> | |||
class HelloWorld | |||
{ | |||
public: // 클래스의 외부에서도 직접 사용하고 수정할 수 있게 노출한다. | |||
HelloWorld() // 클래스가 생성되면 자동 실행되는 생성자 | |||
{ | |||
priv = 0; | |||
} | |||
~HelloWorld() // 클래스가 사라질 때 실행되는 소멸자 | |||
{ | |||
printf("Destructor"); | |||
} | |||
void Hello() | |||
{ | |||
printf("Hello World!"); | |||
} | |||
// private 변수에 접근할 때 | |||
void SetPriv(int value) // Setter | |||
{ | |||
priv = value; | |||
} | |||
int GetPriv() // Getter | |||
{ | |||
return priv; | |||
} | |||
// 함수 오버라이드 (동명의 부모 클래스의 함수와 자식 클래스의 함수의 가능 차별화시키기) | |||
virtual void DisplayClassName() | |||
{ | |||
printf("Class HelloWorld"); | |||
} | |||
protected: // 이 클래스와 자식 클래스에서만 직접 사용하고 수정할 수 있게 노출한다. | |||
// 클래스 선언문이 길어지면 cpp 파일에 함수의 기능을 따로 작성할 수 있다. | |||
void HelloProtected(); | |||
private: // 이 클래스에서만 직접 사용하고 수정할 수 있게 노출한다. | |||
int priv; | |||
} | |||
class NotHello: public HelloWorld | |||
{ | |||
public: | |||
void DisplayClassName override | |||
{ | |||
printf("Class NotHello"); | |||
} | |||
} | |||
// HelloWorld.cpp | |||
#include "HelloWorld.h" | |||
HelloWorld::HelloProtected() | |||
{ | |||
printf("Hello Protected"); | |||
} | |||
</syntaxhighlight> | </syntaxhighlight> |
2024년 7월 9일 (화) 19:24 판
기본 프로그래밍 용어
변수 (Variable)
수학의 미지수와 비슷한 개념으로, 자연수가 될 수도 소수가 될 수도 있지만 자연수로 채택된 변수는 소수가 될 수 없다. 마찬가지로 반대도 불가능하다. 이러한 변수의 등록 형식을 변수의 타입이라 부르며, 자연수와 소수를 같이 연산하려면 둘 중 하나의 타입을 바꾸어야 함 (형변환)
// 변수 선언 형식은:
// '타입' '변수 이름';
int a = 1; // int (Integer, 정수) 타입의 a라는 이름의 변수 선언. a의 값은 1
float b = 1.2f; // float (실수) 타입의 b라는 이름의 변수 선언. b의 값은 1.2
char c = 'a'; // char (Character, 1바이트 글자) 타입의 c라는 이름의 변수 선언. c의 값은 a
bool d = false; // bool (Boolean, 참과 거짓) 타입의 d라는 이름의 변수 선언. d의 값은 거짓 (false)
배열 (Array)
같은 타입의 변수 및 클래스 및 구조체로 이루어진 집합. 리스트라고 생각해도 되지만 엄밀히는 다름
#include <cstdio>
// 배열 선언 형식은:
// '타입' '배열 이름'['배열 길이'] = {'타입에 맞는 값', ..., '배열 길이 - 1개만큼 작성할 것'};
int a[2] = {-1, 1};
float b[3] = {0.5f, 2.4f, 3.6f};
bool c[4]; // 값을 초기화하지 않으면 컴파일되지 않는다.
char d[5] = {'h', 'e', 'l', 'l', 'o'};
int e[] = {1, 2, 3, 4, 5}; // e의 길이는 자동으로 5가 된다.
// 값 꺼내오기
// 배열의 순서는 0부터 시작하므로 a[0]은 -1, a[1]은 1이다.
int main(void) {
printf("%d", a[1]);
return 0;
}
// 결과: 1
함수 (Function)
작업을 수행하기 위해 설계된 코드의 집합으로, 아두이노에서 썼던 println, 프로세싱의 rect 등은 모두 함수이다. 함수의 목적에 따라 입력 값과 출력 값 (Return 값)이 있을 수 있다. 함수를 잘 쓰면 코드의 양이 획기적으로 줄고 가독성이 좋아짐
이벤트 (Event)
- 이벤트 노드 (블루프린트) 에서 노드의 시작점 (코드의 시작)
- 스크래치의 방송과 비슷하면서도 함수와도 비슷함
- 함수와의 차이점은 값을 출력 (리턴)할 수 없음
- 기본적으로 게임이 시작될 때 동작하는 이벤트 (BeginPlay)와 매 프레임마다 동작하는 이벤트 (Tick)이 있음. 이벤트를 만들 수도 있음
클래스 (Class)
OOP (Object-Oriented Programming), 즉 객체지향 프로그래밍에서 사용되는 중요한 개념으로, 객체를 정의하기 위해 변수와 방법을 정의하는 템플릿이다. 예시로, 사람이라는 종이 있다. 여기에는 사람의 장기, 사지 등 모든 사람들의 기본적인 공통점이 정리되어 있다. 하지만 인종, 더 나아가 개개인에 따라 세부적인 특성은 모두 다르다. 여기서 사람이라는 종은 기본적인 템플릿이고, 이 사람이라는 템플릿을 기반으로 개개인에게 차이를 두는 것이다.
클래스는 세부적인 개념으로 파생될 수 있다. 위 예시로는 사람이라는 종을 프로그램에서 클래스라고 가정했을 때 사람 그 자체는 부모 클래스라고 부른다. 여기서 파생되는 황인, 백인, 흑인, 더 나아가 개개인이라는 개체로 분류되는데, 이를 자식 클래스로 비유할 수 있다. 상위 클래스의 공통점을 모두 가진 채 자식 클래스로 파생되는 것을 상속 (Inherit), 또는 확장 (Extend)라고 부른다. 상속된다고 해서 부모 클래스는 상속해준 기능을 잃는 것이 아니라 공유하는 것이다.
프로그래밍 연산자
대입 연산자
=: 등호를 기준으로 오른쪽의 값을 왼쪽에 적용함
#include <cstdio>
int main(void) {
bool a;
a = true; // a에 true를 대입한다.
return 0;
}
사칙 연산
- +: 덧셈
- -: 뺄셈
- *: 곱셈
- /: 나눗셈
- %: 나눗셈의 나머지
#include <cstdio>
int main(void) {
int a;
a = 1 + 2;
printf("%d", a); // 결과는 3
a = 1 - 2;
printf("%d", a); // 결과는 -1
a = 3 * 8;
printf("%d", a); // 결과는 24
a = 3 / 8;
printf("%d", a); // 결과는 0 (정수형이라 0.375에서 소수점이 사라진다)
a = 3 % 8;
printf("%d", a); // 결과는 3
// 지금까지 a의 값은 3입니다.
a = a + 1; // a (3) + 1의 값을 a에 대입한다. 결과는 4
a += 1; // a = a + 1과 동일
return 0;
}
증감 연산자
전위 증감
현재 변수의 값을 사용한 후 변수를 증감시킨다.
int a = 5;
int b = a++; // b에는 5가 할당되고, a는 6이 됨.
후위 증감
변수를 증감시킨 후 그 값을 사용한다.
int a = 5;
int b = ++a; // a는 6으로 증가하고, b에도 6이 할당됨.
표현식에서 사용되는 증감 연산자
아래 예제에서 a++는 현재 값을 사용한 후 증가하고, ++a는 먼저 증가한 후에 값을 사용합니다. 결과적으로 result1과 result2의 값이 다르다.
int a = 5;
int b = 10;
int result1 = a++ + b; // result1은 15가 되고, a는 6이 됨.
int result2 = ++a + b; // a는 7이 되고, result2는 17이 됨.
비교 연산자
- < 및 >: 초과나 미만으로 좌우의 값을 비교했을 때 참이면 true를, 거짓이면 false를 반환
- 3 < 4 == true
- 3 > 4 == false
- <= 및 >=: 이상이나 이하로 좌우의 값을 비교했을 때 참이면 true를, 거짓이면 false를 반환
- 3 ≥ 4 == false
- 3 ≥ 3 == true
- 3 ≤ 4 == true
- 같음 (==): 좌우의 값을 비교하고 같으면 true를, 다르면 false를 반환
- int형 변수 a에 4가 저장되었을 때 a == 4는 true, a == 10은 false를 반환함
- 다름 (!=): 좌우의 값을 비교하고 다르면 true를, 같으면 false를 반환
Boolean (true/false) 연산
true와 false 두 가지를 비교할 때
- AND (&&): 양쪽 다 true일 때 true를 반환함
- true && true == true
- true && false == false
- false && false == false
- OR (||): 둘 중 하나만 true여도 true를 반환함
- true || false == true
- true || true == true
- false || false == false
- eXclusive OR (XOR): true의 개수가 홀수일 때 true를 반환함
기본 문법
조건문
if
if 안에 들어가는 값이 참일 때 코드를 실행한다.
#include <iostream>
void main() {
int a = 1; // 정수형 변수 a를 선언하고 1로 초기화
if(a == 1) {
std::cout << a << std::endl; // a가 1이면 a의 값을 출력한다
}
}
/* 결과는
1
*/
else if
if의 조건이 맞지 않을 때 같은 변수로 다른 조건을 제시한다.
#include <iostream>
void main() {
int a = 3; // 정수형 변수 a를 선언하고 3으로 초기화
if(a == 1) {
std::cout << a << std::endl; // a가 1이면 a의 값을 출력한다
}
else if(a == 3) {
std::cout << a << std::endl; // a가 1은 아니고 3일 때 a의 값을 출력한다
}
}
/* 결과는
3
*/
else
if나 else if의 조건까지 다 맞지 않을 때 나머지 조건이 참일 때 실행함
#include <iostream>
void main() {
int a = 1; // 정수형 변수 a를 선언하고 1로 초기화
if(a == 3) {
std::cout << a << std::endl; // a가 3이면 a의 값을 출력한다
}
else {
std::cout << "Else" << std::endl; // a가 3이 아니면 Else를 출력한다
}
}
/* 결과는
Else
*/
switch-case
switch에 들어가는 어떤 한 변수에 대해서 case에 맞는 값일 때 코드를 실행하고 조건이 다 맞지 않는다면 default를 실행함
#include <cstdio>
void main() {
int a = 1; // 정수형 변수 a를 선언하고 1로 초기화
switch(a) {
case 1: // if(a == 1)
printf("a == 1");
break;
case 2: // if(a == 2)
printf("a == 2");
break;
case 3: // if(a == 3)
printf("a == 3");
break;
default: // else
printf("뭣도 아님");
}
}
/* 결과는
a == 1
*/
반복문
while
while 내 조건이 true일 때 계속해서 반복한다.
#include <iostream>
void main() {
int a = 0; // 정수형 변수 a를 선언하고 0으로 초기화
while(a <= 10) { // a가 10 이하인 경우 계속 반복
std::cout << a << " "; // a의 값을 출력
a++; // 매 반복마다 a에 1을 더함
}
}
/* 결과는
0 1 2 3 4 5 6 7 8 9 10
*/
for
변수 선언, 변수의 범위, 변수의 증감을 직관적으로 일체화한 반복문
#include <iostream>
void main() {
for(int i=0; i<=10; i++) { // i는 0부터 10 이하까지 1씩 증가하며, 11번 반복한다
std::cout << i << " ";
}
// for문 사용 시 선언한 변수 i는 for문 외부에서 사용할 수 없음
}
/* 결과는
0 1 2 3 4 5 6 7 8 9 10
*/
ForEach
배열의 길이만큼 반복하며 n번째 반복 주기에서 n번째 배열 값을 반환한다.
// C#에서의 ForEach
using System;
// ...
int[] numbers = { 4, 5, 6, 1, 2, 3, -2, -1, 0 }; // numbers라는 정수형 배열에 4, 5, 6, 1, 2, 3, -2, -1, 0의 값으로 구성
foreach(int n in numbers) { //
System.Console.Write("{0} ", n);
}
/* 결과는
4 5 6 1 2 3 -2 -1 0
*/
// C++에서의 ForEach (C++11부터 지원)
#include <cstdio>
int main(void) {
int numbers[] = { 4, 5, 6, 1, 2, 3, -2, -1, 0 }; // numbers라는 정수형 배열에 4, 5, 6, 1, 2, 3, -2, -1, 0의 값으로 구성
for(int n: numbers) { //
printf("{0} ", n);
}
return 0;
}
/* 결과는
4 5 6 1 2 3 -2 -1 0
*/
클래스
클래스는 특정 기능을 모듈화 (또는 캡슐화)하여 하나의 단위로 묶는 것을 목표로 한다. 또한, 세부적인 부분을 외부로 드러나지 않게 하여 모듈 간의 결합도를 떨어뜨린다. 이렇게 겉보기로는 불편해보이게 프로그램을 작성하는 이유는 기능이 많아졌을 때 클래스끼리 정해진 방식대로 통신하지 않으면 나중에 그 기능을 수정할 때 수많은 코드를 탐색하고 다시 작성 (리팩토링)해야 할 수 있기 떄문이다.
다음은 HelloWorld라는 이름의 클래스를 만들고, NotHello라는 이름의 HelloWorld의 자식 클래스를 만드는 예제이다.
// HelloWorld.h
#include <cstdio>
class HelloWorld
{
public: // 클래스의 외부에서도 직접 사용하고 수정할 수 있게 노출한다.
HelloWorld() // 클래스가 생성되면 자동 실행되는 생성자
{
priv = 0;
}
~HelloWorld() // 클래스가 사라질 때 실행되는 소멸자
{
printf("Destructor");
}
void Hello()
{
printf("Hello World!");
}
// private 변수에 접근할 때
void SetPriv(int value) // Setter
{
priv = value;
}
int GetPriv() // Getter
{
return priv;
}
// 함수 오버라이드 (동명의 부모 클래스의 함수와 자식 클래스의 함수의 가능 차별화시키기)
virtual void DisplayClassName()
{
printf("Class HelloWorld");
}
protected: // 이 클래스와 자식 클래스에서만 직접 사용하고 수정할 수 있게 노출한다.
// 클래스 선언문이 길어지면 cpp 파일에 함수의 기능을 따로 작성할 수 있다.
void HelloProtected();
private: // 이 클래스에서만 직접 사용하고 수정할 수 있게 노출한다.
int priv;
}
class NotHello: public HelloWorld
{
public:
void DisplayClassName override
{
printf("Class NotHello");
}
}
// HelloWorld.cpp
#include "HelloWorld.h"
HelloWorld::HelloProtected()
{
printf("Hello Protected");
}