Is Goto reasonable in this case? [SFML included]

Hi everybody.
i created a little function to fit graphical representation of a text inside a box, in SFML. i check if the text width is bigger than the box width; if positive, i break the text line and continue; then i check if the text height is bigger than the box height. if positive, i reduce the text font size and start all over again. the issue is, to start all over, i use a goto. but i want some opinions. is it a good option in this case? how else could i do it?
thanks in advance :)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <string>
#include <sstream>

int main(){
    sf::RenderWindow window(sf::VideoMode(800, 600), "MessageBox");
    sf::Font font;
    font.loadFromFile("automati.ttf");
    sf::Text text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam gravida ipsum hendrerit, dignissim ipsum vitae, mattis est. Cras risus magna, lobortis ut neque quis, bibendum varius mi. Nullam quis diam molestie, maximus nibh sed, hendrerit nibh. Curabitur a consequat ipsum, sed imperdiet sem. Integer et quam lacinia, vulputate diam eu, ultrices ipsum. Morbi et orci nec lectus commodo porta convallis et tellus. Quisque et pulvinar arcu. Duis id libero justo. Duis lacinia ante non eros lobortis luctus. Morbi laoreet id mauris sit amet posuere. ", font, 20);
    sf::Vector2f bounds(500, 200);

    std::string str = text.getString();
    std::vector<std::string> words_vector;
    std::stringstream ss(str);
    while(ss >> str){
        words_vector.push_back(str);
    }
    label:
    text.setString("");
    for (int i=0; i<words_vector.size(); i++){
        str = text.getString();
        text.setString(str + " " + words_vector[i]);
        if (text.getLocalBounds().width > bounds.x){
            text.setString(str + "\n" + words_vector[i]);
            if (text.getLocalBounds().height > bounds.y){
                text.setCharacterSize(text.getCharacterSize()*0.95);
                goto label;
            }
        }
    }
    str = text.getString();
    str.erase(0, 1);
    text.setString(str);

    text.setColor(sf::Color::Black);
    while (window.isOpen()){
        sf::Event event;
        while (window.pollEvent(event)){
            if(event.type == sf::Event::Closed){
                window.close();
            }
        }
        window.clear(sf::Color::White);
        window.draw(text);
        window.display();
        sf::sleep(sf::milliseconds(10));
	}
}
is it a good option in this case?
No.
how else could i do it?
Simply use a while instead of if:
1
2
3
            while (text.getLocalBounds().height > bounds.y){
                text.setCharacterSize(text.getCharacterSize()*0.95);
            }
Move this loop before the loop for the word break.

This reduces the amount of trys for getting the desired result.
goto is almost never the best option. I can't recall using it ever in serious code (Ive been known to do whatever gets it done in throw-away code). Like a global variable, it can make things easier and simpler for those occasional 10 line programs that one writes every so often.
And even if you use goto (which again you shouldn't) don't call your label 'label'.
Simply use a while instead of if:
1
2
3
while (text.getLocalBounds().height > bounds.y){
                text.setCharacterSize(text.getCharacterSize()*0.95);
}

Move this loop before the loop for the word break.


do you mean like this?

1
2
3
4
5
6
7
8
9
10
11
    text.setString("");
    for (int i=0; i<words_vector.size(); i++){
        str = text.getString();
        text.setString(str + " " + words_vector[i]);
        if (text.getLocalBounds().width > bounds.x){
            while (text.getLocalBounds().height > bounds.y){
                text.setCharacterSize(text.getCharacterSize()*0.95);
            }
            text.setString(str + "\n" + words_vector[i]);
        }
    }


it's not the same thing. it gives me this (the red line is the bounding box):
https://postimg.org/image/njcneg7d9/
with goto it works:
https://postimg.org/image/uzbx092sd/

please not that if "text.getLocalBounds().height > bounds.y" happens, i have to reduce the font size a little and start all over again, because smaller font means that i could have more words in a single line. it's not jut about reducing font size until the text fits vertical space; because like this i could waste horizontal space. i want the text to fill the box in the best way possible.

thanks in advance again :)
I don't think the use of goto is horrible here, but sticking some of that in a function makes things a lot clearer, IMO.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bool will_fit(sf::Vector2f bounds, sf::Text& t, const std::vector<std::string>& words) {
    t.setString("");

    for (std::size_t i = 0; i < words.size(); ++i) {
        std::string msg = t.getString();
        t.setString(msg + " " + words[i]);

        if (t.getLocalBounds().width > bounds.x) {
            t.setString(msg + '\n' + words[i]);
            if (t.getLocalBounds().height > bounds.y)
                return false;
        }
    }

    return true;
}


Then the goto+loop becomes:

1
2
3
    while (!will_fit(bounds, text, words_vector)) {
        text.setCharacterSize(text.getCharacterSize()*0.95);
    }




Is goto reasonable in this case?

I'll let you decide:

Apple's 'goto fail' tells us nothing good about Cupertino's software delivery process
http://www.zdnet.com/article/apples-goto-fail-tells-us-nothing-good-about-cupertinos-software-delivery-process/
Topic archived. No new replies allowed.