Strange character at the end of lines when hovering over the screen

I am working on a game with a dialog box that has text while you read it, like in an RPG. I got it to work, but my only problem is when I draw on the screen there is a weird character that I didn’t enter or on the keyboard. I have a gif below to demonstrate.

Failed Dialogue Gif

Here's my code:

TextRenderer.h

#ifndef TEXTRENDERER_H
#define TEXTRENDERER_H
#include <SFML/Graphics.hpp>
#include <iostream>

using namespace sf;
using namespace std;

class TextRenderer {
    public:
        Texture *t;
        Sprite sprite;
        string currentString, fullString, eBeforeString;
        int currentWordNum, onTheLine;
        vector<string> words;
        Text drawableText;
        Font font;
        Clock charTime;
        TextRenderer();
        void update();
        void newText(string nText);
};

#endif // TEXTRENDERER_H

      

TextRenderer.cpp

#include "TextRenderer.h"
#include <SFML/Graphics.hpp>
#include <iostream>
#include <cstring>

using namespace sf;
using namespace std;

TextRenderer::TextRenderer() {
    t = new Texture;
    t->loadFromFile("data/images/talkScreen.png");
    sprite.setTexture(*t);
    sprite.setOrigin(sprite.getGlobalBounds().width/2, 0);
    sprite.setScale(4, 4);
    font.loadFromFile("data/fonts/VCR_OSD_MONO_1.001.ttf");
    drawableText.setFont(font);
    drawableText.setFillColor(Color::White);
    drawableText.setCharacterSize(30);
    currentWordNum = 0; /// Initializing variables
    currentString = "";
    eBeforeString = "";
}

void TextRenderer::update() {
    /// If the current word number (spot in the words vector) is less than
    /// the size of the words vector
    if (currentWordNum < words.size()) {
        if (currentString.length() < words.at(currentWordNum).length()) {
            if (charTime.getElapsedTime().asSeconds() >= 0.02) {
                currentString = words.at(currentWordNum).substr(0, currentString.length() + 1);
                charTime.restart();
                onTheLine += 1;
            }
        } else if (currentString == words.at(currentWordNum)) {
            /// If you just finished typing a word
            if (charTime.getElapsedTime().asSeconds() >= 0.02) {
                eBeforeString += currentString + " ";
                currentString = "";
                currentWordNum += 1;
                onTheLine += 1;
                if (currentWordNum != words.size()) {
                    if (onTheLine + words.at(currentWordNum).length() >= 53) {
                        eBeforeString += "\n";
                        onTheLine = 0;
                    }
                }
            }
        }
    }
    drawableText.setString(eBeforeString + currentString);
}

void TextRenderer::newText(string nText) {
    fullString = nText;
    /// Breaking the string into 'words' which I add to a vector
    char eStr[fullString.length()];
    for (unsigned i = 0; i < fullString.size(); i++) {
        eStr[i] = fullString.at(i);
    }
    char *spt = strtok(eStr, " ");
    while (spt != NULL) {
        words.push_back(spt);
        spt = strtok(NULL, " ");
    }
    currentString = "";
    eBeforeString = "";
    currentWordNum = 0;
    onTheLine = 0;
    drawableText.setString(currentString);
    drawableText.setPosition(sprite.getPosition().x + 20 - sprite.getGlobalBounds().width/2, sprite.getPosition().y + 10);
    charTime.restart();
}

      

And in main.cpp, I just call

textScreen.newText("Look at the symbol at the very end of this string on the other side of this period .");

      

+3


source to share


2 answers


1201ProgramAlarm's answer solves the closest problem, but I have a different view.

strtok

is a delay with C. It uses it, but it requires you to leave comfort std::string

for the wild and woolly world of c-strings and either dynamic allocation or the custom Variable Length Array used by the OP. It also has potential glitches due to the fact that it is written for simpler problems from simpler times. For example, everyone strtok

uses the same internal buffer. The obvious consequences of threads were solved with local thread storage, and the remaining problem of two or more concurrent strtok

in one thread is solved with strtok_r

(re-entrant strtok

), but seeing that we are coding in C ++ we could handle this with threads as well C ++.

Instead, I can suggest



void TextRenderer::newText(string nText) {
    fullString = nText;

// replacement starts here
    istringstream in(nText);
    string word; 
    while (in >> word) {
        words.push_back(word);
    }
//end replacement

    currentString = "";
    eBeforeString = "";
    currentWordNum = 0;
    onTheLine = 0;
    drawableText.setString(currentString);
    drawableText.setPosition(sprite.getPosition().x + 20 - sprite.getGlobalBounds().width/2, sprite.getPosition().y + 10);
    charTime.restart();
}

      

This completely removes the need for eStr

(which hurts me because I like egg hunting) and reduces the code to an easy-to-read 5ft.

Istringstream documentation.

+2


source


strtok

expects a string to be passed to it as a C style string and ends with a NUL ( '\0'

) character . The string you pass to ( eStr

) is not, so the last call strtok

goes past the end of your array, resulting in Undefined Behavior.



You need to add one extra character to the size eStr

and set the last character to '\0'

(or 0).

+2


source







All Articles