TEXT("") variable as FString::Printf() parameter

Hi!
How could I use TEXT("") in a variable so I could use it as FString::Printf() parameter? I can’t understand what’s going on:


// Error: auto Format = Total < 100 ? TEXT("%02d/%02d") : TEXT("%03d/%03d");
// Error: FString Format = Total < 100 ? FString(TEXT("%02d/%02d")) : FString(TEXT("%03d/%03d"));
// Error: FText Format = Total < 100 ? FText::FromString(TEXT("%02d/%02d")) : FText::FromString(TEXT("%03d/%03d"));

FString FormattedText = FString::Printf(Format, Turn, TurnTotal);

The code below works, but I’d like to understand why the code above doesn’t:


if (Total < 100)
{
FString FormattedText = FString::Printf(TEXT("%02d/%02d"), Turn, TurnTotal);
}
else
{
FString FormattedText = FString::Printf(TEXT("%03d/%03d"), Turn, TurnTotal);
}

Thank you!

Like so:



FString::Printf(TEXT("MyText %s", "SomeOtherText"));

or

FString SomeOtherText = TEXT("Something");
FString::Printf(TEXT("MyText %s", *SomeOtherText));


2 Likes

Thank you @TheJamsh !

I didn’t explain it properly,
What I’d like to do is store the first FString::Printf() parameter in a variable, because it can have two values:



// **Error: auto Format** = Total < 100 ? TEXT("%02d/%02d") : TEXT("%03d/%03d");
// **Error: FString Format** = Total < 100 ? FString(TEXT("%02d/%02d")) : FString(TEXT("%03d/%03d"));
// **Error: FText Format** = Total < 100 ? FText::FromString(TEXT("%02d/%02d")) : FText::FromString(TEXT("%03d/%03d"));

FString FormattedText = **FString::Printf**(**Format**, Turn, TurnTotal);

But the code above doesn’t work.

What do you mean by “doesn’t work”? It would be helpful if you could add compiler error messages.

Also: Try making Format an FString and then do something like this, maybe?


FString::Printf(*Format, Turn, TurnTotal);

Edit: Keep in mind that if you work with FString, you need to dereference it to get access to the wchar_t* behind it.

Thank you @Kyoril ,
By doesn’t work I mean compiler error in the first parameter:

I don’t know how to use a variable with this parameter.

You can’t use FText like that in Printf. It is not what you think, FText is a struct completely unrelated to the TEXT macro.

FText has a ToString() function you can use, but as Bruno says FText is not really for this.

You can find info on UE4’s string types here:

1 Like

I’m having the same problem.

This compiles:


FString formatted = FString::Printf(TEXT("test"), TEXT("123"));

This doesn’t:


const TCHAR* a = TEXT("test");
FString formatted = FString::Printf(a, TEXT("123"));

Same error as described avove.

1 Like

Hi @DarthSomebody](https://forums.unrealengine.com/member/491832-darthsomebody), @SolidSk](https://forums.unrealengine.com/member/1364026-solidsk)

Please, check FString::Format



const int32 MyInt = 12;
const float MyFloat = 0.12f;
const FString MyString = FString(TEXT("MyStringValue"));

//const FString MyStringPrintf = FString::Printf(TEXT("MyStringPrintf: {0}, {1}, {2}"));
const FString MyStringPrintf = FString(TEXT("MyStringPrintf: {0}, {1}, {2}"));

const FString MyStringFormatted = FString::Format(*MyStringPrintf, { MyInt, MyFloat, MyString });

UE_LOG(LogTemp, Warning, TEXT("MyStringFormatted: %s"), *MyStringFormatted);


My comment on Answerhub for the same question:
https://answers.unrealengine.com/que…comment-989170

Hope this helps.:slight_smile:

4 Likes

If you are like me a you are looking for a way to print a FText into a PrintF, here is the way to do:

FText::FromString(FString::Printf(TEXT("%s"), *GrantedRecipe.GameName.ToString())

Note:

  1. You have to make sure that the Format String is a TEXT("") (and not only a "simple-literal-string")
  2. De-reference FText with a * and .ToString()

https://www.flogamedev.com/2023/07/18/fprintf-in-unreal-engine-with-text-ftext-and-fstring/

3 Likes

the function FString::Printf first param finally is turn to type “WIDECHAR”
image
so I try to use wchar_t to set,it work

FString Str = TEXT("%sTestAAA");
FString Result;
wchar_t FormatStr[256];

wcscpy_s(FormatStr, TCHAR_TO_WCHAR(*Str));
Result = FString::Printf(FormatStr, TEXT("This"));

I hope can help you

1 Like

I leave my solution here if someone comes across this thread and is still interested in an answer to the original question:

template <typename... ArgumentTypes>
FString MyPrintf(const FString& Format, ArgumentTypes... Args)
{
    // Note that for some reason the format parameter of 'FString::Printf' does not work with other variables only with
    // char[] literals. This is enforced by static assertions. We can use this static buffer though to copy the pattern
    // over. Not sure what the rationale behind this limitation is.
    //
    static TCHAR FormatBuffer[128];

    // Make sure to check that the format string is not longer than the buffer.
    // We use '<' instead of '<=' because 'Len' does not include the '\0' char. See implementation of 'FString::Len()'.
    if (!ensureMsgf(Format.Len() < UE_ARRAY_COUNT(FormatBuffer),
                    TEXT("Format string '%s' (length %d) exceeds the maximum size of %d"), *Format, Format.Len(),
                    UE_ARRAY_COUNT(FormatBuffer)))
    {
        return FString();
    }

    // Copy the format string to the buffer.
    TCString<TCHAR>::Strcpy<UE_ARRAY_COUNT(FormatBuffer)>(FormatBuffer, *Format);
    
    return FString::Printf(FormatBuffer, Args...);
}

Note that this function requires a constant maximum length of the format string. In my case 128. If you have longer format strings you need to use a larger buffer.

Example usage:

FColor Color = FColor::Cyan;
FString FormatString = TEXT("(R=%d,G=%d,B=%d,A=%d)");
    
FString Result = MyPrintf(FormatString, Color.R, Color.G, Color.B, Color.A);

Result: (R=0,G=255,B=255,A=255)