C++ 界面上的奇怪文本打印

C++ 界面上的奇怪文本打印,c++,sdl,truetype,C++,Sdl,Truetype,我不知道这里发生了什么,尽管这很酷而且奇怪的令人毛骨悚然,但这并不是我真正想要的 基本上;我正在尝试实现一个程序,在黑色界面上缓慢地键入文本。我正在使用SDL2和SDL2_TTF来实现这一点,到目前为止一切都进展顺利 目前,我让它在黑屏上键入“嘿;)”,但下面是发生的情况: 忽略FPS计数器,这只是Nvidia 我真的不知道发生了什么,我使用的字体是“Hack Regular.ttf” 关于代码: #include<iostream> #include<SDL.h> #

我不知道这里发生了什么,尽管这很酷而且奇怪的令人毛骨悚然,但这并不是我真正想要的

基本上;我正在尝试实现一个程序,在黑色界面上缓慢地键入文本。我正在使用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;
}
#包括
#包括
#包括
#包括
无效句柄事件(SDL_事件e,bool*quit){
而(SDL_事件(&e)>0){
如果(e.type==SDL\u退出){
*退出=真;
}
}
}
无效渲染(SDL_渲染器*渲染器,SDL_纹理*文本渲染器,SDL_Rect srcret,SDL_Rect dstrect){
SDL_渲染器(渲染器);
SDL_RenderCopy(渲染器、textToRender、srcrect和dstrect);
SDL_渲染器呈现(渲染器);
}
void printToConsole(标准::字符串消息,字符*文本){
对于(int i=0;i
如果很难阅读,我很抱歉,我觉得没有必要使用多个类


需要注意的是,“f”是“asdf”的最后一个字母。我最初将文本定义为,不知道它为什么从这里开始。

在下面的语句中,您定义了一个占用1字节内存的变量,并将整数值102(也称为“f”)存储在ascii中:

char text = 'asdf'; //This is the text that has been rendered.
上述说法存在几个问题:

  • 单个
    char
    变量只能存储一个字符、一个字节的内存。您正在尝试分配4。只有最后一个值保持不变
  • 您试图使用单个字符,而您想使用
  • 您正在对c字符串使用单引号语法
  • 由于变量只存储一个字节,因此该单个值之后的下一个内存字节是未定义的—它来自程序中其他地方的任意内存,可能是堆栈上下一个分配的任何值
  • 如果您正确地声明了该变量,那么稍后您将尝试写入只读内存,因为c字符串文本通常加载到只读内存中
然后,通过获取变量的地址并将其作为
char*
类型传递,将该值传递给呈现例程:

textSurface = TTF_RenderText_Solid(font, &text, color);
然而,在C/C++中,
char*
习惯性地用于存储指向a的指针,即带有最终空终止符的字符序列。在接受
char*
参数作为c字符串的API中,您需要传递一个指向末尾带有空终止符的字符序列的指针

因为它希望传递的值是c字符串,所以它将从内存中盲读,直到看到一个值为0的字节。由于它读取的内容超过了为该变量(只有一个字节)预留的内存的末尾,因此它将读取任意内存,直到它幸运地在某处找到一个零为止——这就是它显示垃圾的原因

你怎么解决这个问题?好吧,这取决于你将如何得到你的字符串

使用您提供的代码,没有真正的理由分配您自己的c字符串。如果您有
string
对象,可以使用
c\u str()
方法访问
char*
c-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
变量,传递给程序的其他部分对其进行修改,然后让main打印设置的任何值,您可以执行以下操作:

#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";
}
#包括
#包括
#包括
使用名称空间std;
无效开始(字符串和文本);
int main(){
//创建一个空的“字符串”对象,调用默认构造函数;
//这为我们提供了一个有效的空字符串对象。
字符串文本;
...
while(true){
...
//通过引用传递'text'变量。
开始(文本);
textSurface=TTF_RenderText_Solid(字体,text.c_str(),颜色);
...
}
}
//通过引用获取字符串对象,并对其进行修改以填充它
//我们想要的文本。
无效开始(字符串和文本){
text+=“你好”;
文本+=”;
文本+=“世界”;
}
为什么
start()
使用
char
参数而不是
char*
?无论哪种方式,都可以使用<