我正在开发一个小型C库来教授视频游戏编程,我创建了一个简单的功能来在屏幕上绘制格式化文本(即得分,生活)。功能是:
const char *FormatText(const char *text, ...)
{
int length = strlen(text);
char *buffer = malloc(length + 20);
va_list args;
va_start(args, text);
vsprintf(buffer, text, args);
va_end(args);
return buffer;
}
此功能在主游戏循环中使用,在Draw部分中,如下所示:
DrawText(FormatText("%02i", score), 10, 10, 40, BLACK);
DrawText()函数中的额外参数,只表示屏幕坐标X,Y,字体大小和颜色。
我每秒呼叫这个功能大约60次(甚至更多),所以,如果我是对的,我会在每次呼叫时分配新内存......而且我'永远不要释放那段记忆!
如何以同样的方式继续使用我的功能来解决这个问题?
我的第一个想法是在我的库上创建一个全局char *缓冲区,在初始化时分配它并一直重用它......但我不确定这是不是最好的主意,我试试避免太多全局变量。
非常感谢您的回答!
再次感谢大家的回答。
最后我解决这个问题的方法是使用:
const char *FormatText(const char *text, ...)
{
static char buffer[MAX_FORMATTEXT_LENGTH];
va_list args;
va_start(args, text);
vsprintf(buffer, text, args);
va_end(args);
return buffer;
}
可能不是最好的解决方案,但我认为它对于lib的用户来说是最好的,而不必担心内存管理。
这是一个简单的用法示例:
#include "raylib.h"
int main()
{
int score = 100020;
int hiscore = 200450;
int lives = 5;
InitWindow(800, 450, "testing FormatText()");
SetTargetFPS(60);
while (!WindowShouldClose()) // Detect window close button or ESC key
{
BeginDrawing();
ClearBackground(RAYWHITE);
DrawText(FormatText("Score: %08i", score), 80, 80, 20, RED);
DrawText(FormatText("HiScore: %08i", hiscore), 80, 120, 20, GREEN);
DrawText(FormatText("Lives: %02i", lives), 80, 160, 40, BLUE);
DrawText(FormatText("Elapsed Time: %02.02f ms", GetFrameTime()*1000), 80, 220, 20, BLACK);
EndDrawing();
}
CloseWindow();
return 0;
}
结果是:
答案 0 :(得分:1)
我将管理内存的责任传递给父功能。它会根据需要分配和释放,而不是FormatText()
本身
// somefunction
char *buffer;
buffer = malloc(<somesize>);
if (buffer) {
FormatText(buffer, "%02i", ...);
free(buffer);
}
答案 1 :(得分:0)
你的函数几乎已经存在于某些Libc中,如GNU libc,它被称为asprintf(3)。调用者应该free
malloc
- ed缓冲区。
您可以将其用作:
char* msg=NULL;
DrawText((msg=FormatText("%02i", score)), 10, 10, 40, BLACK);
free (msg);
或者,如果使用asprintf
,则使用comma operator,
char* msg=NULL;
DrawText((asprintf(&msg,"%02i",score),msg), 10, 10, 40, BLACK);
free (msg);
最后,如果您因为应该调用free
而感到困扰,您可以决定整个程序使用Boehm garbage collector(因此您打电话给GC_MALLOC
并且不要#39;打扰GC_FREE
)。然后你要定义
char* GC_sprintf(const char*fmt, ...) {
char buf[128];
va_list ap;
va_start (ap, fmt);
int sz = vsnprintf(buf, sizeof(buf), fmt, ap);
va_end (ap);
if (sz < sizeof(buf)) return GC_strdup (buf);
char* gcbuf = GC_MALLOC_ATOMIC (sz+1);
memset (gcbuf, 0, sizeof (gcbuf));
va_start (ap, fmt);
vsnprintf(gcbuf, sz, fmt, ap);
va_end (ap);
return gcbuf;
}
然后直接致电
DrawText(GC_sprintf("%02i",score), 10, 10, 40, BLACK);
BTW,由于"%02i"
格式产生一个短字符串,您可以使用
char locbuf[8];
snprintf (locbuf, sizeof(locbuf), "%02i", score);
DrawText(locbuf, 10, 10, 40, BLACK);
您甚至可以考虑定义可变参数DrawText_printf
并调用
DrawText_printf(10, 10, 40, BLACK, "%02i", score);