// Fill out your copyright notice in the Description page of Project Settings.
#include "MyGameInstance.h"
void UMyGameInstance::Init()
{
Super::Init();
TCHAR LogCharArray[] = TEXT("Hello Unreal"); // TCHAR 배열로 문자열 저장
UE_LOG(LogTemp, Log, LogCharArray);
// FString 에 TCHAR 배열 넣기
// TArray 라고 하는 언리얼이 제공하는 동적 배열 클래스 방식으로 문자열이 보관됨
// 동적 배열에서 실제 데이터를 꺼낼 때는 동적 배열이 속하고 있는 내부 자료에 대한 포인터를 가져와서 넘겨줘야 함. 이때 사용하는 것이 포인터 연산자(*)
// 문자열의 맨 처음 포인터 반환
FString LogCharString = LogCharArray;
UE_LOG(LogTemp, Log, TEXT("%s"), *LogCharString); // 인자로 들어갈 때 포인터 연산자를 꼭 넣어줘야 함.
const TCHAR* LogCharPtr = *LogCharString;
TCHAR* LogCharDataPtr = LogCharString.GetCharArray().GetData(); // 실제 TCHAR 의 포인터를 가져옴. 메모리에 직접 접근해서 이용할 수 있음
// FCString 은 C런타임 수준에서 문자열을 처리하는 클래스
TCHAR LogCharArrayWithSize[100];
// 저수준의 복사
FCString::Strcpy(LogCharArrayWithSize, LogCharString.Len(), *LogCharString);
if (LogCharString.Contains(TEXT("unreal"), ESearchCase::IgnoreCase)) // IgnoreCase 는 대소문자 구분 안 한다는 의미
{
int32 Index = LogCharString.Find(TEXT("unreal"), ESearchCase::IgnoreCase); // unreal 이 시작하는 인댁스
FString EndString = LogCharString.Mid(Index); // unreal 이 시작하는 위치에서부터 끝까지 잘라줌
UE_LOG(LogTemp, Log, TEXT("Find Test: %s"), *EndString);
}
// Split 함수
// 이렇게 해야 오류가 안 나네여;;;
/*
FString Left, Right;
if (LogCharString.Split(TEXT(" "), &Left, &Right))
{
UE_LOG(LogTemp, Log, TEXT("Split Test: %s 와 %s"), *Left, *Right);
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Failed to split the string."));
}
이렇게만 하면 오류남;;
*/
if (!LogCharString.IsEmpty())
{
FString Left, Right;
if (LogCharString.Split(TEXT(" "), &Left, &Right))
{
// 중간에 한글 '와' 가 뒤집힌 물음표로 출력됨
// 코드를 작성할 때 윈도우에서 한글을 썼기 때문에 CP949 형태의 멀티 바이트 스트링으로 저장돼서 UTF16 을 쓰는 언리얼과 호환이 안 되는 거임
// 이럴 땐 파일 세이브버튼 누르고 옵션 버튼 눌러서 Save with Encoding 을 누르고 Encoding 을 UTF8 로 바꿔주기~
UE_LOG(LogTemp, Log, TEXT("Split Test: %s 와 %s"), *Left, *Right);
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Failed to split the string."));
}
}
else
{
UE_LOG(LogTemp, Warning, TEXT("LogCharString is empty!"));
}
// 변환 함수
int32 IntValue = 32;
float FloatValue = 3.141592;
FString FloatIntString = FString::Printf(TEXT("Int:%d Float %f"), IntValue, FloatValue);
FString FloatString = FString::SanitizeFloat(FloatValue);
FString IntString = FString::FromInt(IntValue);
UE_LOG(LogTemp, Log, TEXT("%s"), *FloatIntString);
UE_LOG(LogTemp, Log, TEXT("Int:%s Float:%s"), *IntString, *FloatString);
// int 스트링을 다시 Int 로 변환해보기
int32 IntValueFromString = FCString::Atoi(*IntString);
// float 스트립을 다시 float 으로 변환해보기
float FloatValueFromString = FCString::Atof(*FloatString);
FString FloatIntString2 = FString::Printf(TEXT("Int:%d Float %f"), IntValueFromString, FloatValueFromString);
UE_LOG(LogTemp, Log, TEXT("%s"), *FloatIntString2);
// FName 의 활용
// FName: 애셋 관리를 위해 사용되는 문자열 체계
// -> 대소문자 구분 없음
// -> 한번 선언되면 바꿀 수 없음
// -> 가볍고 빠름
// -> 문자를 표현하는 용도가 아닌 애셋 키를 지정하는 용도로 사용. 빌드시 해시값으로 변환됨.
// 언리얼은 FName 과 관련된 글로벌 Pool 자료구조를 가지고 있음
// 값들이 결국 해시 값으로 변환돼서 FName 에는 문자열 정보가 들어가는 것이 아닌 키 값만 들어감.
FName key1(TEXT("PELVIS"));
FName key2(TEXT("pelvis"));
UE_LOG(LogTemp, Log, TEXT("FName 비교 결과 : %s"), key1 == key2 ? TEXT("같음") : TEXT("다름")); // 대소문자를 구분하지 않기 때문에 둘은 같음
// FName 사용 주의점
for (int i = 0; i < 10000; ++i)
{
// FName 의 생성자에 문자열을 넣으면 FName 이 하는 일은 문자열을 Key 로 변환한 다음에 긔 Key 가 전역 Pool 에 있는지를 조사하는 작업을 거치게됨
// 즉, 오버헤드가 발생할 수 있음(for 문에서 생성하면)
FName SearchInNamePool = FName(TEXT("pelvis"));
// const 로 한번만 처리하도록 하자
// 처음 초기화할 때 데이터를 저장하고 그 다음부터는 찾을 일이 없음
const static FName StaticOnlyOnce(TEXT("pelvis"));
}
// FText: 다국어 지원을 위한 문자열 관리 체계
// -> 일종의 키로 작용함.
// -> 별도의 문자열 테이블 정보가 추가로 요구됨.
// -> 게임 빌드 시 자동으로 다양한 국가별 언어로 변환됨.
}
// FString 에 TCHAR 배열 넣기
// TArray 라고 하는 언리얼이 제공하는 동적 배열 클래스 방식으로 문자열이 보관됨
// 동적 배열에서 실제 데이터를 꺼낼 때는 동적 배열이 속하고 있는 내부 자료에 대한 포인터를 가져와서 넘겨줘야 함. 이때 사용하는 것이 포인터 연산자(*)
// 문자열의 맨 처음 포인터 반환
FString LogCharString = LogCharArray;
UE_LOG(LogTemp, Log, TEXT("%s"), *LogCharString); // 인자로 들어갈 때 포인터 연산자를 꼭 넣어줘야 함.
3. 포인터
첫번째 줄은 맨 앞 포인터를 가져오지만 데이터 수정 불가. 두번째 줄은 데이터 수정 가능
const TCHAR* LogCharPtr = *LogCharString;
TCHAR* LogCharDataPtr = LogCharString.GetCharArray().GetData(); // 실제 TCHAR 의 포인터를 가져옴. 메모리에 직접 접근해서 이용할 수 있음
4. 복사
LogCharArrayWithSize 에 LogCharString 을 복사함.
// FCString 은 C런타임 수준에서 문자열을 처리하는 클래스
TCHAR LogCharArrayWithSize[100];
// 저수준의 복사
FCString::Strcpy(LogCharArrayWithSize, LogCharString.Len(), *LogCharString);
5. 나누기1
if (LogCharString.Contains(TEXT("unreal"), ESearchCase::IgnoreCase)) // IgnoreCase 는 대소문자 구분 안 한다는 의미
{
int32 Index = LogCharString.Find(TEXT("unreal"), ESearchCase::IgnoreCase); // unreal 이 시작하는 인댁스
FString EndString = LogCharString.Mid(Index); // unreal 이 시작하는 위치에서부터 끝까지 잘라줌
UE_LOG(LogTemp, Log, TEXT("Find Test: %s"), *EndString);
}
6. 나누기2
if (!LogCharString.IsEmpty())
{
FString Left, Right;
if (LogCharString.Split(TEXT(" "), &Left, &Right))
{
// 중간에 한글 '와' 가 뒤집힌 물음표로 출력됨
// 코드를 작성할 때 윈도우에서 한글을 썼기 때문에 CP949 형태의 멀티 바이트 스트링으로 저장돼서 UTF16 을 쓰는 언리얼과 호환이 안 되는 거임
// 이럴 땐 파일 세이브버튼 누르고 옵션 버튼 눌러서 Save with Encoding 을 누르고 Encoding 을 UTF8 로 바꿔주기~
UE_LOG(LogTemp, Log, TEXT("Split Test: %s 와 %s"), *Left, *Right);
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Failed to split the string."));
}
}
else
{
UE_LOG(LogTemp, Warning, TEXT("LogCharString is empty!"));
}
7. 변환 함수
// 변환 함수
int32 IntValue = 32;
float FloatValue = 3.141592;
FString FloatIntString = FString::Printf(TEXT("Int:%d Float %f"), IntValue, FloatValue);
FString FloatString = FString::SanitizeFloat(FloatValue);
FString IntString = FString::FromInt(IntValue);
UE_LOG(LogTemp, Log, TEXT("%s"), *FloatIntString);
UE_LOG(LogTemp, Log, TEXT("Int:%s Float:%s"), *IntString, *FloatString);
// int 스트링을 다시 Int 로 변환해보기
int32 IntValueFromString = FCString::Atoi(*IntString);
// float 스트립을 다시 float 으로 변환해보기
float FloatValueFromString = FCString::Atof(*FloatString);
FString FloatIntString2 = FString::Printf(TEXT("Int:%d Float %f"), IntValueFromString, FloatValueFromString);
UE_LOG(LogTemp, Log, TEXT("%s"), *FloatIntString2);
8. FName
// FName 의 활용
// FName: 애셋 관리를 위해 사용되는 문자열 체계
// -> 대소문자 구분 없음
// -> 한번 선언되면 바꿀 수 없음
// -> 가볍고 빠름
// -> 문자를 표현하는 용도가 아닌 애셋 키를 지정하는 용도로 사용. 빌드시 해시값으로 변환됨.
// 언리얼은 FName 과 관련된 글로벌 Pool 자료구조를 가지고 있음
// 값들이 결국 해시 값으로 변환돼서 FName 에는 문자열 정보가 들어가는 것이 아닌 키 값만 들어감.
FName key1(TEXT("PELVIS"));
FName key2(TEXT("pelvis"));
UE_LOG(LogTemp, Log, TEXT("FName 비교 결과 : %s"), key1 == key2 ? TEXT("같음") : TEXT("다름")); // 대소문자를 구분하지 않기 때문에 둘은 같음
// FName 사용 주의점
for (int i = 0; i < 10000; ++i)
{
// FName 의 생성자에 문자열을 넣으면 FName 이 하는 일은 문자열을 Key 로 변환한 다음에 긔 Key 가 전역 Pool 에 있는지를 조사하는 작업을 거치게됨
// 즉, 오버헤드가 발생할 수 있음(for 문에서 생성하면)
FName SearchInNamePool = FName(TEXT("pelvis"));
// const 로 한번만 처리하도록 하자
// 처음 초기화할 때 데이터를 저장하고 그 다음부터는 찾을 일이 없음
const static FName StaticOnlyOnce(TEXT("pelvis"));
}