我不知道这里发生了什么,虽然它很酷而又奇怪地令人毛骨悚然,但这并不是我想到的。
基本上;我正在尝试实现一个在黑色界面上减慢文本类型的程序。我正在使用SDL2和SDL2_TTF来实现这一点,事情进展顺利。
忽略FPS计数器,那只是Nvidia。
老实说,我不知道发生了什么,我使用的字体是“Hack-Regular.ttf”。
代码:
#include<iostream>
#include<SDL.h>
#include<string>
#include<SDL_ttf.h>
void handleEvents(SDL_Event e, bool* quit){
while(SDL_PollEvent(&e) > 0){
if(e.type == SDL_QUIT){
*quit = true;
}
}
}
void render(SDL_Renderer* renderer, SDL_Texture* textToRender, SDL_Rect srcrect, SDL_Rect dstrect){
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, textToRender, &srcrect, &dstrect);
SDL_RenderPresent(renderer);
}
void printToConsole(std::string message, char* text){
for(int i = 0; i < message.length(); i++){
*text = *text + message.at(i);
SDL_Delay(30);
}
}
void start(char text){
printToConsole("Hey ;)", &text);
}
int main( int argc, char *argv[] ) {
SDL_Init(SDL_INIT_EVERYTHING);
TTF_Init();
SDL_Window* window = SDL_CreateWindow("Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 600, 600, SDL_RENDERER_ACCELERATED);
SDL_Renderer* renderer = SDL_CreateRenderer(window, 0, 0);
char text = 'asdf'; //This is the text that has been rendered.
bool quit = false;
SDL_Event e;
TTF_Font* font = TTF_OpenFont("Hack-Regular.ttf", 28);
SDL_Color color = {255, 255, 255};
SDL_Surface* textSurface;
SDL_Texture* textTexture;
SDL_Rect srcrect;
SDL_Rect dstrect;
srcrect.x = 0;
srcrect.y = 0;
srcrect.w = 100;
srcrect.h = 32;
dstrect.x = 640/2;
dstrect.y = 480/2;
dstrect.w = 100;
dstrect.h = 32;
while(!quit){
handleEvents(e, &quit);
render(renderer, textTexture, srcrect, dstrect);
start(text);
textSurface = TTF_RenderText_Solid(font, &text, color);
textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);
}
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
window = NULL;
renderer = NULL;
TTF_Quit();
SDL_Quit();
return 0;
}
如果难以阅读,我表示道歉,我觉得不需要使用多个班级。
需要注意的是,“f”是'asdf'的最后一个字母我最初定义文本,不知道为什么它从那里开始。
答案 0 :(得分:2)
在下面的语句中,定义一个占用1个字节内存的变量,并存储整数值102,即ascii中的'f':
char text = 'asdf'; //This is the text that has been rendered.
以上陈述存在以下几个问题:
char
变量只能存储一个字符,一个字节的内存。您正尝试分配4.仅保留最后一个值。然后通过获取变量的地址并将其作为char*
类型传递,将该值传递给渲染例程:
textSurface = TTF_RenderText_Solid(font, &text, color);
但是,在C / C ++中,char*
惯用于存储指向'c-string'的指针 - 即具有最终空终止符的字符序列。在接受char*
参数作为c字符串的API中,您需要将指针传递给末尾带有空终止符的字符序列。
因为它希望传递的值是一个c字符串,所以它会盲目地从内存中读取,直到它看到一个值为0的字节。因为它正在读取超出为该变量预留的内存的末尾(这是只有一个字节),它会读取任意内存,直到它变得幸运并在某处找到零 - 因此它显示为垃圾。
...
你如何解决这个问题?那么,这取决于你将如何获得你的字符串。
使用您提供的代码,没有理由分配您自己的c字符串。如果您有string
个对象,则可以使用char*
方法访问c_str()
c-string兼容缓冲区;只要您没有修改string
,返回的指针就有效,并且由于返回的指针归string
所有,您无需担心清理它。
// Use the string class's implicit conversion from a c-string literal to
// a `std::string` object.
std::string text = "hello world";
...
while(!quit){
handleEvents(e, &quit);
render(renderer, textTexture, srcrect, dstrect);
// Note the lack of a call to the `start` method here.
textSurface = TTF_RenderText_Solid(font, text.c_str(), color);
textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);
}
如果你想要引用语义 - 也就是说,有一个你在main中声明的text
变量,传递给你的程序的其他部分修改它,然后让你的主要打印任何值是设置,您可以执行以下操作:
#include <stdlib.h>
#include <stdio.h>
#include <string>
using namespace std;
void start(string& text );
int main() {
// Create an empty 'string' object', invoking the default constructor;
// This gives us a valid empty string object.
string text;
...
while(true) {
...
// The `text` variable is passed by reference.
start(text);
textSurface = TTF_RenderText_Solid(font, text.c_str(), color);
...
}
}
// Takes a string object by reference, and modifies it to fill it
// with our desired text.
void start( string& text ) {
text += "Hello";
text += " ";
text += "World";
}