Formatting a string on a variadic parameter function without using GC

Mike Parker via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Mar 1 20:12:13 PST 2016


On Wednesday, 2 March 2016 at 01:39:13 UTC, David G. Maziero 
wrote:

> Consider the following function:
>
> void RenderText( FontBMP font, int x, int y, const char* text )
> {

> 	for( int r=0; text[r]!='\0'; ++r )
> 	{

You're asking for trouble here. There's no guarantee that any D 
string is going to be null terminated. String literals are, but 
beyond that, all bets are off.


>
> 	char[256] text;
> 	sprintf( &text[0], "Player: pos:%.3f - speed:%.3f", 
> player.position, player.speed );

Instead of sprintf, look into using std.format.sformat [1] (see 
below). It's equivalent to std.format.format, but allows you to 
provide a buffer.


> 	RenderText( font, 0, 0, cast(char*)text );

It's considered bad form to cast an array to a pointer like this. 
If you need a pointer to an array, just use the ptr property: 
text.ptr. Always be aware of the null terminator situation, 
though, when passing to C.

>
> I could simply do "RenderText(font,0,0,"FPS: "~to!string(fps));"

Won't compile without using the .ptr property (or casting, which 
again, you shouldn't do). Moreover, you run into the null 
terminator problem. "FPS :" will be null terminated because it's 
a literal, but the string produced by concatentating it with the 
result of to!string would not be.

> but I want to avoid GC entirely.
> The ideal scenario is to have something like "void RenderText( 
> /*etc*/, const char* fmt, ... )" but I can't seem to figure a 
> way to pass the variadic parameters to sprintf.
>
> Any ideas?

With sformat, something like this (not tested):

import std.format;
char buf[1024];
auto fmt = sformat(buf, "Foo: %s", 42);
if(fmt.length < buf.length) buf[fmt.length] = 0;
else buf[$-1] = 0;
RenderText(blah, blah, buf.ptr);

sformat returns a slice of the buffer containing the formatted 
string. You can use its length to guarantee the buffer is null 
terminated.




More information about the Digitalmars-d-learn mailing list