그냥 게임개발자
네번째 - 여러가지 문자열 사용 방법(TCHAR, FString) 본문
저번에 Hello, World를 UE_LOG라는 매크로를 통해 화면에 출력시켰죠?
이번에는 우리는 TCHAR와 FString을 배울것입니다.
TCHAR
TCHAR가 뭐냐?
string같은 거다.
진짜 간단하게 이야기하자면 이게 끝이다.
왜 언리얼은 그러면 string을 사용하면 되지 왜 TCHAR를 만들어서 사용하는 거지?
라고 필자는 생각했었다.
일단 역사를 거슬러서 살펴보면 1990년대 후반에 이르러서야 아시아 문자열이 표준화가 되었다
뭐 한국어, 중국어, 일본어 등등 이런거 말이다.
하지만 컴퓨터는 아시아권에서 표준화가 되기도 전에 이미 사용이 되고 있었다.
영어는 1byte로 충분히 표현이 가능했지만, 아시아권 문자는 1byte로 표현이 불가능했었다.
그 때 당시에는 나름 각 국가별로 고유한 문자를 표현하기 위한 방법들을 구현해서 컴퓨터에 적용시키고 있었다.
우리나라에서는 EUC-KR이라는 체계로 시작되어 Windows95에서 이것을 발전시킨 CP949라는 체계로 만들어져서 한글을 처리하기 시작했었다.
이러한 체계를 Multibyte문자열이라고 한다.
근데 90년대 후반에 들어서 완전히 유니코드가 정착이 되어 이후에 나온 운영체제들은 다 유니코드를 지원하게 되는데, 문제는 마이크로소프트가 개발한 이 Multibyte 문자열 체계가 지금 아직도 Windows운영체제에 널리널리 쓰이고 있다는 것이다.
즉 Singlebyte(ANSI, ASCII), Multibyte(EUC-KR, CP949), Unicode(UTF-8, UTF-16) 우리가 처리해야 될 문자열이 총 3개가 된 것이다.
이 3개의 문자열을 한꺼번에 처리하고 해결해주는 것은 언리얼에서 TCHAR다.
후 오늘도 역사 공부 열심히했다.
사실 나도 이 글을 읽으면서 엥? 신기하면서도 각 사람들이 정말 많은 것을 만들었구나 라고 생각이 든다.
아무튼 그래서 TCHAR와 FString을 사용하는데
FString은 뭐야?
저번 글에 설명했다.
C++표준라이브러리가 생기기전에 이미 언리얼에서는 멀티플랫폼을 대체하기 위해 자체적으로 라이브러리를 만들었다.
그래서 FString을 사용한다고 한다.
그렇대요.
자 그러면 TCHAR와 FString을 사용해 출력을 해보자.
MyGameInstance.cpp
void UMyGameInstance::Init()
{
Super::Init();
static const TCHAR LogCharArray[] = TEXT("Hello, World");
UE_LOG(LogTemp, Log, LogCharArray);
}
저번과 조금 다르지 않은가?
void UMyGameInstance::Init()
{
Super::Init();
UE_LOG(LogTemp, Log, TEXT("%s"), TEXT("Hello, World"));
}
이런식으로 사용했었는데 말이다.
사실 TEXT는 기본적으로 TCHAR의 배열이다.
아 그리고 UE5.1버전에서는 UE_LOG가 TCHAR 배열을 근야 써도 오류가 나지 않았지만, UE5.2 이상 부터는 static const를 지정해줘야 한다.
FString
만약 문자열을 다양하게 조합하고 싶다면 TCHAR 배열이 아닌 FString을 사용
void UMyGameInstance::Init()
{
Super::Init();
static const TCHAR LogCharArray[] = TEXT("Hello, World");
UE_LOG(LogTemp, Log, LogCharArray);
FString LogCharString = LogCharArray;
UE_LOG(LogTemp, Log, TEXT("%s"), *LogCharString);
}
이런식으로 FString을 사용하면 되는데, FString은 TCHAR의 헬퍼 클래스이다.
그래서 여러가지 기능을 제공해준다.
데이터를 자르거나, 붙이거나, 새로운 방식으로 불러 들이거나 다양한 연산이 가능하다.
여기서 UE_LOG 매크로는 3번째 파라미터에는 항상 배열만 들어가는데
TCHAR는 배열이니 그냥 들어가고, FString은 %s에 대응 될 때 TCHAR의 포인터 Array를 반환해줘야 한다.
그니까 FString에 TCHAR의 배열을에 넣었을 때 TArray라고 하는 언리얼 엔진이 제공하는 동적 배열 클래스 방식으로 문자열을 보관한다.
이 동적 배열(FString)에서 다시 실제 데이터(TCHAR)를 꺼낼 때는 내부 자료에 대한 포인터를 가져와서 넘겨줘야 한다.
그래서 포인터 연산자를 사용하게 되면 FString에 포함하고 있는 동적배열 즉 TArray에 포함하고 있는 데이터의 첫번째 인자 포인터를 반환 해준다.
말이 어렵죠?
쉽게 말하면 FString에 들어있는 문자열은 포인터를 사용해 배출해줘야 데이터가 나온다라는 겁니다.
아래의 그림을 보면 좀 쉬울 거에요

FString에 대입할 때는 동적배열로 바뀌고 실제 문자열 데이터를 꺼낼때는 *연산자를 사용해 꺼내야 한다는 것!
이해 가셨죠?
이제 아까 말했듯이 FString 여러가지 기능이 붙어있는 문자열 클래스라고 했다.
여러가지 포인터 활용
static const TCHAR LogCharArray[] = TEXT("Hello, World");
FString LogCharString = LogCharArray;
// 불변하지 않는 포인터 배열을 생성
// FString의 TCHAR의 포인터 주소를 가져옴
const TCHAR* LongCharPtr = *LogCharString;
// 포인터를 받아 직접 고치고 싶으면 FString 안에
// TArray의 첫번째 인자의 포인터를 가져오는 방법
TCHAR* LogCharDataPtr = LogCharString.GetCharArray().GetData();
복사
// 배열로 가져오고 싶으면 저수준 복사 사용
TCHAR LogCharArrayWithSize[100]; // 배열 크기 설정
// 복사된 문자열이 저장될 배열, FString의 크기 만큼 버퍼지정
FCString::Strcpy(LogCharArrayWithSize, LogCharString.Len(), *LogCharString);
FCString은 C런타임 수준에서 문자열을 처리하는 클래스이다.
그니까 C라이브러리에서 제공하는 기본적인 스트링 관련 함수를 가지고 있다.
뭐 문자열 찾거나, 자르거나, 복사 등의 기능을 가지고 있고 그런 기능들을 처리 담당하는 클래스가 FCString이다.
검색과 자르기
// unreal string이 존재하는지와 조건은
// ESearchCase::IgnoreCase(대소문자 구분X)
// ESearchCase::CaseSensitive(대소문자 구분O)
if (LogCharString.Contains(TEXT("unreal"), ESearchCase::IgnoreCase))
{
// 몇 번째 인덱스에 unreal이라는 문자가 있는지 찾을 수 있음
int32 Index = LogCharString.Find(TEXT("unreal"), ESearchCase::IgnoreCase);
FString EndString = LogCharString.Mid(Index); // EndString은 unreal의 인덱스를 받았기에
UE_LOG(LogTemp, Log, TEXT("Find Test : %s"), *EndString); // unreal에 인덱스부터 출력
}
FString Left, Right;
if (LogCharString.Split(TEXT(" "), &Left, &Right))
{
UE_LOG(LogTemp, Log, TEXT("Split Test : %s 와 %s"), *Left, *Right)
}
어려워 보인다 어려워 보여.
천천히 읽으면 안어렵다.
Split이 자르기 라는 함수도 알고 Find가 찾는 함수라는 것도 알고 ㅇㅇ
천천히 읽어보기 바란다.
FString → int32, float
// ASCII To Int를 활용해 int로 변환
int32 IntValueFromString = FCString::Atoi(*IntString);
float FloatValueFromString = FCString::Atof(*FloatString);
FString FloatIntString2 = FString::Printf(TEXT("Int:%d Float:%f"), IntValueFromString, FloatValueFromString);
UE_LOG(LogTemp, Log, TEXT("%s"), *FloatIntString2);
int32, float → FString
FString NewString = FString::FromInt(YourInt);
FString VeryCleanString = FString::SanitizeFloat(YourFloat);
다음에는 FName으로... 오늘은 좀 진지하게 써버렸네;;
'Unreal스터디 > Unreal압축판' 카테고리의 다른 글
세번째 - 언리얼 C++ 코딩 표준 (2) | 2024.03.12 |
---|---|
두번째 - Hello World (2) | 2024.03.12 |
첫번째 - 시작하기전 각오 (0) | 2024.03.10 |