# FString研究
此文为FString (opens new window)的原创翻译加总结,本文内容版权归原文所有,仅供学习,如需转载望注本文地址,翻译不易,谢谢理解。
不像FName和FText,FString是唯一一个允许操作字符串的类,有很多方法可以操作字符串,包括改变大小写,摘取子字符串,或者反转字符串,FStrings可以被查找,改变和其他字符串比较。但是,这些操作让FStrings比那些不改变字符串的类花销更大。
# 创建FStrings
FString TestHUDString = FString(TEXT("This is my test FString."));
# 其他类型对比
# FName
它一般用在为资源命名或访问资源时使用,它的特点有:
- 同一字符串在内存中只存储一次,内部有一个hash值,不能被修改。
- 不区分大小写。
- 查找和访问速度比较快。
# FString
类似标准库的std::string,它的特点:
- 可修改,每份存储都是单独内存。
- 区分大小写。
# FText
相关资料:
面向本地化类,它的作用:
- 逐字地创建本地文本
- 格式化文本(从一个占位符模式生成文本)
- 从数字生成文本
- 从日期和时间生成文本
- 生成其他格式的文本,比如大写或小写
# 转换
# 字符串变量之间
# FString转换成其他
From | To | 例子 |
---|---|---|
FString | FName | TestHUDName = FName(*TestHUDString); |
FString | FText | TestHUDText = FText::FromString(TestHUDString); |
- FString->FName,这个转换过程有点危险,因为FName是不区分大小写的,所以这个转换过程是由损耗的。
- FString->FText,这个转换过程有时候是合法的,请意识到FString的内容并不能受益于FText的自动本地化。
# 其他转换成FString
From | To | 例子 |
---|---|---|
FName | FString | TestHUDString = TestHUDName.ToString(); |
FText | FString | TestHUDString = TestHUDText.ToString(); |
- FText->FString,这个转换过程有点危险,从其他语言转换时会有丢失东西的可能。
# 数字和其他变量
# 其他类型转换成FString
变量类型 | 转换形式 | 字符串格式 |
---|---|---|
float | FString::SanitizeFloat(FloatVariable); | |
double | FString::SanitizeFloat(DoubleVariable); | |
int | FString::FromInt(IntVariable); | |
bool | InBool ? TEXT("true") : TEXT("false"); | "true"或"false" |
FVector | VectorVariable.ToString(); | 'X= Y= Z=' |
FVector2D | Vector2DVariable.ToString(); | 'X= Y=' |
FRotator | RotatorVariable.ToString(); | 'P= Y= R=' |
FLinearColor | LinearColorVariable.ToString(); | '(R=,G=,B=,A=)' |
UObject | (InObj != NULL) ? InObj->GetName() : FString(TEXT("None")); | UObject's FName |
对于其他数值转换,你可以以合适的参数来使用FString::Printf()函数。
# FString转换成其他类型
变量类型 | 转换形式 |
---|---|
bool | TestHUDString.ToBool(); |
int | FCString::Atoi(*TestHUDString); |
int64 | FCString::Atoi64(*targetString); |
float | FCString::Atof(*TestHUDString); |
double | FCString::Atod(*targetString); |
char* | const char* result = TCHAR_TO_UTF8(*FStringVar); |
string | std::string result = TCHAR_TO_UTF8(*targetStr); |
# string相关
相关资料:
# string转换为其他
变量类型 | 转换 |
---|---|
FString | FString result = stdstringVar.c_str() |
char* | const char* result = stdstringVar.c_str() |
# 其他转化为string
变量类型 | 转换 |
---|---|
int | string result = to_string(intVar) |
char* | string result = TargetVar |
char[] | string result = TargetVar |
# 比较
重载==操作符可以用来比较两个FStrings,或者将FString同TCHAR*数组比较。因此也有FString::Equals()方法,可以和FString比较,然后用一个ESearchCase枚举来指明比较过程中是否应该忽略大小写,如果想忽略大小写,传入ESearchCase::IgnoreCase,如果不想忽略大小写,请传入ESearchCase::CaseSensitive。
TestHUDString.Equals(TEXT("Test"), ESearchCase::CaseSensitive);
# 查找
在使用FString查找时,有两种搜索类型,第一种,使用FString::Contains(),如果找到了子串就返回true,否则返回false。FString::Contains()可以查找一个String或一个TCHAR*子串。第二个参数ESearchCase枚举可以用来指定是否在查找过程中忽略大小写,第三个参数ESearchDir枚举用来指明查找的方向,默认是忽略大小写,然后从头开始查找。
TestHUDString.Contains(TEXT("Test"), ESearchCase::CaseSensitive, ESearchDir::FromEnd);
第二种查找是使用FString::Find(),返回第一次查找到子串的位置,FString::Find()既可以查找一个FString又可以查找一个TCHAR*子串,就像FString::Contains()一样,可以指定是否忽略大小写和查找方向,默认是忽略大小写然后在字符串的开始查找,你也可以选择指定在字符串内开始的位置,如果FString::Find()找不到子串,它会返回-1。
TestHUDString.Find(TEXT("test"), ESearchCase::CaseSensitive, ESearchDir::FromEnd, 10);
# 构建FStrings
有两种方法来构建子字符串,从子串连接或其他变量类型来构建。先说第一种方法,从子字符串连接,这把FString作为参数,在连接字符串前你需要将其他类型的变量转换成FString;那第二种方法,使用Printf,可以将数字类型的变量,像int和float这样的作为输入,这就允许你将输入的类型添加给字符串。
# 字符串连接
有两种方法来连接字符串:
操作符 | 描述 | 用法 |
---|---|---|
+= | 将提供的字符串附加到FString对象的后面 | StringResult += AddedString; |
+ | 创建一个新的FString对象,然后将提供的字符串附加到后面 |
# Printf
FStrings可以使用FString::Printf被保存到FStrings里,也可以像下面那样作为调试信息输出到屏幕上。它里面的格式参数和C++的printf函数中的格式化参数一行,请看下面的例子:
FString AShooterHUD::GetTimeString(float TimeSeconds)
{
// only minutes and seconds are relevant
const int32 TotalSeconds = FMath::Max(0, FMath::TruncToInt(TimeSeconds) % 3600);
const int32 NumMinutes = TotalSeconds / 60;
const int32 NumSeconds = TotalSeconds % 60;
const FString TimeDesc = FString::Printf(TEXT("%02d:%02d"), NumMinutes, NumSeconds);
return TimeDesc;
}
2
3
4
5
6
7
8
9
10
注意,当使用%s参数来输出FStrings时,必须使用*操作符来返回TCHAR*。
# 操作FStrings
有很多函数可以用来操作字符串,我们会在这提及一些,要想看到全部可用的FString函数,请查看UnrealString.h文件或者FString的API文档。有很多函数用来拷贝一个字符串的一部分,比如Left,Right和Mid。你可以在找到子串的位置将一个字符串分成两个字符串,这时候可以使用Split方法。其他的方法比如ParseIntoArray用来分割字符串,可以将一个字符串通过指定的分隔符分割成字符串数组。可以通过使用ToUpper和ToLower来完成大小写转换,它们分别将字符串转换成大写或小写。
# HUDs中的FString
# Canvas
为了在HUD中使用功能Canvas将FString显示,可以调用FCanvas::DrawText()函数:
Canvas->DrawText(BigFont, TestHUDString, 110.0f,110.0f);
注意,你必须在你的HUD类的DrawHUD()函数中调用DrawText()函数,或者在以DrawHUD()开始的调用链中的函数调用。
# 调试信息
为了调试,FStrings可以被打印到Viewport和Output Log。
# 打印到Viewport
为了将调试信息打印到Viewport,使用UEngine::AddOnScreenDebugMessage()方法。这个函数将按顺序接收如下参数:
参数名 | 参数类型 | 描述 |
---|---|---|
key | int | 一个用来防止将同样的信息被多次添加到屏幕的唯一键,使用-1可以让你的调试信息短暂出现。 |
TimeToDisplay | float | 这个信息要显示多久,以秒为单位 |
DisplayColor | FColor | 文本要显示的颜色 |
DebugMessage | FString | 要显示的调试信息 |
例子:
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Blue, TestHUDString);
# 打印到OutputLog
UE_LOG使用打印格式参数。
UE_LOG(LogClass, Log, TEXT("This is a testing statement. %s"), *TestHUDString);
- LogClass是日志的分类,你可以使用一个存在的分类(在OutputDevices.h文件中的DECLARE_LOG_CATEGORY_EXTERN宏设置),或者你可以使用DEFINE_LOG_CATEGORY_STATIC来定义自己的分类。
- Log分为几个等级,它在ELogVerbosity枚举中定义好了,有效值是Fatal,Error,Warning,Display,Log,Verbose或者VeryVerbose。
- 下一个参数是你想要的输出的文本,包含格式参数。
注意,上面的例子使用了%s参数,所以需要使用*操作符来返回TCHAR*。
使用UE_LOG打印的信息可以在在Output Log窗口查看,在UE4编辑器中是Window>Output Log
# 转换编码宏
FString构建在一个包含TCHARS的TArray之上。有很多可用宏可转换一个应用字符串(TCHAR*)成ANSI或UNICODE字符集,反之亦然,这些宏的定义可在Engine\Source\Runtime\Core\Public\Containers\StringConv.h文件中找到。
如果字符串是相对比较小的,空间分配作为转换类的一部分是在栈上;否则会使用堆来分配临时的缓冲区。在使用堆前,它的大小是一个模板参数,你可以在应用中利用这点进行调整,这在循环中是安全的因为类的作用域脱离了栈的分配区域。
常见的转换宏是:
- TCHAR_TO_ANSI - 转换一个引擎字符串(TCHAR*)成一个ANSI。
- ANSI_TO_TCHAR - 转换一个ANSI字符串成一个引擎字符串(TCHAR*)。
注意,这些宏声明的对象有很短的生命周期,它们可被用于函数的参数,你不能给被转换字符串分配一个变量,因为这个对象会在离开作用域后被释放。
警告,你传入的参数必须是一个合适的字符串,因为参数会通过类型转换被分配给一个指针。如果你传入了一个TCHAR而不是TCHAR*,它会通过编译,但是在运行时会崩溃。它们的使用方法是:SomeApi(TCHAR_TO_ANSI(SomeUnicodeString));