# FString研究

此文为FString (opens new window)的原创翻译加总结,本文内容版权归原文所有,仅供学习,如需转载望注本文地址,翻译不易,谢谢理解。

不像FName和FText,FString是唯一一个允许操作字符串的类,有很多方法可以操作字符串,包括改变大小写,摘取子字符串,或者反转字符串,FStrings可以被查找,改变和其他字符串比较。但是,这些操作让FStrings比那些不改变字符串的类花销更大。

# 创建FStrings

FString TestHUDString = FString(TEXT("This is my test FString."));
1

# 其他类型对比

# FName

它一般用在为资源命名或访问资源时使用,它的特点有:

  1. 同一字符串在内存中只存储一次,内部有一个hash值,不能被修改。
  2. 不区分大小写。
  3. 查找和访问速度比较快。

# FString

类似标准库的std::string,它的特点:

  1. 可修改,每份存储都是单独内存。
  2. 区分大小写。

# 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);
1

# 查找

在使用FString查找时,有两种搜索类型,第一种,使用FString::Contains(),如果找到了子串就返回true,否则返回false。FString::Contains()可以查找一个String或一个TCHAR*子串。第二个参数ESearchCase枚举可以用来指定是否在查找过程中忽略大小写,第三个参数ESearchDir枚举用来指明查找的方向,默认是忽略大小写,然后从头开始查找。

TestHUDString.Contains(TEXT("Test"), ESearchCase::CaseSensitive, ESearchDir::FromEnd);
1

第二种查找是使用FString::Find(),返回第一次查找到子串的位置,FString::Find()既可以查找一个FString又可以查找一个TCHAR*子串,就像FString::Contains()一样,可以指定是否忽略大小写和查找方向,默认是忽略大小写然后在字符串的开始查找,你也可以选择指定在字符串内开始的位置,如果FString::Find()找不到子串,它会返回-1。

TestHUDString.Find(TEXT("test"), ESearchCase::CaseSensitive, ESearchDir::FromEnd, 10);
1

# 构建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;
}
1
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);
1

注意,你必须在你的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);
1

# 打印到OutputLog

UE_LOG使用打印格式参数。

UE_LOG(LogClass, Log, TEXT("This is a testing statement. %s"), *TestHUDString);
1
  • 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));