3
\$\begingroup\$

This is a follow up of Cleaning a file / Word Query

I incorporated the suggestions from the anwers there and turned the Word Query Programm into a GUI.

enter image description here enter image description here enter image description here

For that I used the Support code of the Book which provides some basic functions for FLTK GUI toolkit. You can find it here: http://www.stroustrup.com/Programming/PPP2code/

However I modified the code slightly because I didn't want to use the std_lib_facilities.h provided by Stroustrup since it includes a lot of bloat by including many headers which are not necessary.

First of all I would like you to check the GUI implementation. Let me know if you find improvements for the code. Are there any bad practices? You can find it in Word_query_window.h/cpp.

Feel also free to take a look in Cleaned_words.h/cpp and Word_query.h/cpp. They are improved Versions of the files provided in the original question without GUI: Cleaning a file / Word Query

In Word_query.h I would especially like to know how to simplify

std::vector<std::pair<Word, Occurences>> most_frequent_words(const std::map<Word, Occurences>& words_with_occurences);
std::vector<Word> longest_words(const std::map<Word, Occurences>& words_with_occurences);
std::vector<Word> shortest_words(const std::map<Word, Occurences>& words_with_occurences);

These functions were changed from the last question to here by returning more than one result. I feel like I compute the results to complicated. Also the three methods look quite similar in the implementation.

The other files they are basically all from Stroustrup with std_lib_facilities.h removed as an include. I think it would be also interesting what could be improved in them nowadays. The Book is based on C++11 but feel also free to suggest improvements here using the latest standard (C++17).

If you want this GUI get to run. I used MSVC 2017 and followed this tutorial how to get install FLTK to run: https://bumpyroadtocode.com/2017/08/05/how-to-install-and-use-fltk-1-3-4-in-visual-studio-2017-complete-guide/

Here is the source code in order from important to less important:

Word_query_window.h

#ifndef WORD_QUERY_WINDOW_GUARD_280820182111
#define WORD_QUERY_WINDOW_GUARD_280820182111

#include "Window.h"
#include "GUI.h"
#include "Point.h"

#include <fstream>
#include <map>

namespace word_query_gui {

    using Word = std::string;
    using Occurences = int;

    class Word_query_window : public Graph_lib::Window {
    public:
        Word_query_window();
    private:
        void init_window_open_file();
        void show_window_open_file();
        void hide_window_open_file();

        void init_window_show_filename();
        void show_window_show_filename();
        void hide_window_show_filename();

        void init_window_select();
        void show_window_select();
        void hide_window_select();

        void init_window_display();
        void show_window_display();
        void hide_window_display();

        static const Point window_offset_xy;
        static constexpr auto window_size_x = 1024;
        static constexpr auto window_size_y = 768;
        static constexpr auto window_label = "Word query";

        static constexpr auto   button_size_x = (window_size_x / 100) * 13;
        static constexpr auto   button_size_y = (window_size_y / 100) * 8;

        // Error
        static const Point      text_error_xy;
        static constexpr auto   text_error_font_size = (window_size_y / 100) * 8;
        static constexpr auto   text_error_color = Graph_lib::Color::red;
        static constexpr auto   text_error_label_invalid = "Invalid input";
        static constexpr auto   text_error_label_no_file = "File does not exist";
        Graph_lib::Text         text_error;

        // "Window" open file
        static const Point      in_box_filename_xy;
        static constexpr auto   in_box_filename_size_x = (window_size_x / 100) * 59;
        static constexpr auto   in_box_filename_size_y = button_size_y;
        static constexpr auto   in_box_filename_label = "Enter Filename ";
        static constexpr auto   in_box_filename_label_size = in_box_filename_size_y;
        static constexpr auto   in_box_filename_text_size = in_box_filename_size_y;
        Graph_lib::In_box       in_box_filename;

        static const Point      button_open_file_xy;
        static constexpr auto   button_open_file_size_x = button_size_x;
        static constexpr auto   button_open_file_size_y = button_size_y;
        static constexpr auto   button_open_file_label = "Open";
        Graph_lib::Button       button_open_file;
        void                    button_open_file_event();

        // "Window" show filename
        static const Point      button_change_file_xy;
        static constexpr auto   button_change_file_size_x = button_size_x * 150 / 100;
        static constexpr auto   button_change_file_size_y = button_size_y;
        static constexpr auto   button_change_file_label = "Change File";
        Graph_lib::Button       button_change_file;
        void                    button_change_file_event();

        static const Point      text_current_filename_xy;
        static constexpr auto   text_current_filename_font_size = button_change_file_size_y;
        static constexpr auto   text_current_filename_color = Graph_lib::Color::black;
        Graph_lib::Text         text_current_filename;

        // "Window" Select
        static constexpr auto   window_select_count_of_buttons = 7;
        static constexpr auto   window_select_button_size_y = (window_size_y - button_change_file_size_y) / window_select_count_of_buttons;

        static const Point      button_occurences_xy;
        static constexpr auto   button_occurences_size_x = button_size_x * 150 / 100;
        static constexpr auto   button_occurences_size_y = window_select_button_size_y;
        static constexpr auto   button_occurences_label = "Occurences of:";
        Graph_lib::Button       button_occurences;
        void                    button_occurences_event();

        static const Point      in_box_occurences_xy;
        static constexpr auto   in_box_occurences_size_x = (window_size_x / 100) * 59;
        static constexpr auto   in_box_occurences_size_y = window_select_button_size_y;
        static constexpr auto   in_box_occurences_label = "";
        static constexpr auto   in_box_occurences_label_size = (window_select_button_size_y / 100) * 90;
        static constexpr auto   in_box_occurences_text_size = (window_select_button_size_y / 100) * 90;
        Graph_lib::In_box       in_box_occurences;

        static const Point      text_occurences_xy;
        static constexpr auto   text_occurences_font_size = window_select_button_size_y;
        static constexpr auto   text_occurences_color = Graph_lib::Color::black;
        Graph_lib::Text         text_occurences;

        static const Point      button_most_frequent_xy;
        static constexpr auto   button_most_frequent_size_x = button_size_x * 150 / 100;
        static constexpr auto   button_most_frequent_size_y = window_select_button_size_y;
        static constexpr auto   button_most_frequent_label = "Most frequent Word";
        Graph_lib::Button       button_most_frequent;
        void                    button_most_frequent_event();

        static const Point      button_longest_xy;
        static constexpr auto   button_longest_size_x = button_size_x * 150 / 100;
        static constexpr auto   button_longest_size_y = window_select_button_size_y;;
        static constexpr auto   button_longest_label = "Longest Word";
        Graph_lib::Button       button_longest;
        void                    button_longest_event();

        static const Point      button_shortest_xy;
        static constexpr auto   button_shortest_size_x = button_size_x * 150 / 100;
        static constexpr auto   button_shortest_size_y = window_select_button_size_y;
        static constexpr auto   button_shortest_label = "Shortest Word";
        Graph_lib::Button       button_shortest;
        void                    button_shortest_event();

        static const Point      button_starting_with_xy;
        static constexpr auto   button_starting_with_size_x = button_size_x * 150 / 100;
        static constexpr auto   button_starting_with_size_y = window_select_button_size_y;
        static constexpr auto   button_starting_with_label = "Words starting with:";
        Graph_lib::Button       button_starting_with;
        void                    button_starting_with_event();

        static const Point      in_box_starting_with_xy;
        static constexpr auto   in_box_starting_with_size_x = (window_size_x / 100) * 59;
        static constexpr auto   in_box_starting_with_size_y = window_select_button_size_y;
        static constexpr auto   in_box_starting_with_label = "";
        static constexpr auto   in_box_starting_with_label_size = (window_select_button_size_y / 100) * 90;
        static constexpr auto   in_box_starting_with_text_size = (window_select_button_size_y / 100) * 90;
        Graph_lib::In_box       in_box_starting_with;

        static const Point      button_with_len_xy;
        static constexpr auto   button_with_len_size_x = button_size_x * 150 / 100;
        static constexpr auto   button_with_len_size_y = window_select_button_size_y;
        static constexpr auto   button_with_len_label = "Words with len:";
        Graph_lib::Button       button_with_len;
        void                    button_with_len_event();

        static const Point      in_box_with_len_xy;
        static constexpr auto   in_box_with_len_size_x = (window_size_x / 100) * 59;
        static constexpr auto   in_box_with_len_size_y = window_select_button_size_y;
        static constexpr auto   in_box_with_len_label = "";
        static constexpr auto   in_box_with_len_label_size = (window_select_button_size_y / 100) * 90;
        static constexpr auto   in_box_with_len_text_size = (window_select_button_size_y / 100) * 90;
        Graph_lib::In_box       in_box_with_len;

        static const Point      button_show_all_xy;
        static constexpr auto   button_show_all_size_x = button_occurences_size_x;
        static constexpr auto   button_show_all_size_y = window_select_button_size_y;
        static constexpr auto   button_show_all_label = "Show all Words";
        Graph_lib::Button       button_show_all;
        void                    button_show_all_event();

        // "Window" display
        static const Point      button_display_back_xy;
        static constexpr auto   button_display_back_size_x = button_size_x;
        static constexpr auto   button_display_back_size_y = button_size_y;
        static constexpr auto   button_display_back_label = "Back";
        Graph_lib::Button       button_display_back;
        void                    button_display_back_event();

        static const Point      button_previous_page_xy;
        static constexpr auto   button_previous_page_size_x = button_size_x;
        static constexpr auto   button_previous_page_size_y = button_size_y;
        static constexpr auto   button_previous_page_label = "Previous Page";
        Graph_lib::Button       button_previous_page;
        void                    button_previous_page_event();

        static const Point      button_next_page_xy;
        static constexpr auto   button_next_page_size_x = button_size_x;
        static constexpr auto   button_next_page_size_y = button_size_y;
        static constexpr auto   button_next_page_label = "Next Page";
        Graph_lib::Button       button_next_page;
        void                    button_next_page_event();

        static const Point                      text_display_xy;
        static constexpr auto                   text_display_font_size = in_box_filename_size_y / 2;
        static constexpr auto                   text_display_offset_y = text_display_font_size;
        static constexpr auto                   text_display_color = Graph_lib::Color::black;
        Graph_lib::Vector_ref<Graph_lib::Text>  text_display;

        template<typename T>
        void init_text_display(const T& container);

        static constexpr auto   text_display_entrys_per_page = ((window_size_y - text_current_filename_font_size - button_next_page_size_y) / text_display_font_size) - 1;

        int page{ 0 };
        void print_page();

        std::string current_filename;
        std::map<Word, Occurences> words_in_file;
    };

    inline bool file_exists(const std::string& filename) {
        std::ifstream f(filename.c_str());
        return f.good();
    }

    inline void init_element(Graph_lib::Window& window, Graph_lib::Text& text, int font_size, Graph_lib::Color color)
    {
        window.attach(text);
        text.set_font_size(font_size);
        text.set_color(color);
    }

    inline void init_element(Graph_lib::Window& window, Graph_lib::Button& button)
    {
        window.attach(button);
        button.hide();
    }

    inline void init_element(Graph_lib::Window& window, Graph_lib::In_box& in_box, int text_size, int label_size)
    {
        window.attach(in_box);
        in_box.set_text_size(text_size);
        in_box.set_label_size(label_size);
        in_box.hide();
    }

    inline void make_gui_text_output(Graph_lib::Vector_ref<Graph_lib::Text>& texts, const std::string& output, Point pos_xy)
    {
        texts.push_back(new Graph_lib::Text{ pos_xy,output });
    }

    inline void unselect(Graph_lib::Button& button)
        // dirty hack to make button not longer preselected after it was pushed
    {
        button.hide();
        button.show();
    }

    inline std::string make_gui_output(const std::pair<Word, Occurences>& p)
    {
        return p.first + "      " + std::to_string(p.second);
    }

    inline std::string make_gui_output(const Word& p)
    {
        return p;
    }

    template<typename T>
    void Word_query_window::init_text_display(const T& container)
    {
        int entrys = 0;
        for (const auto& element : container) {
            if (entrys == text_display_entrys_per_page) {       // for case start display on order
                entrys = 0;
            }
            make_gui_text_output(text_display, make_gui_output(element),
                Point{ text_display_xy.x, text_display_xy.y + text_display_offset_y * entrys });
            ++entrys;
        }
    }

    int word_query_application();
}
#endif

Word_query_window.cpp

#include "Word_query_window.h"

#include "Word_query.h"
#include "Cleaned_words.h"

namespace word_query_gui {

    const Point Word_query_window::window_offset_xy{ Point{ 50,50 } };

    const Point Word_query_window::text_error_xy{ Point{ window_offset_xy.x + (window_size_x / 100) * 50,window_offset_xy.y } };

    // "Window" open file
    const Point Word_query_window::in_box_filename_xy{ Point{ (window_size_x / 100) * 43,window_offset_xy.y + in_box_filename_size_y } };
    const Point Word_query_window::button_open_file_xy{ Point{ window_size_x - button_open_file_size_x - (window_size_x / 100) * 2,in_box_filename_xy.y + in_box_filename_size_y } };

    // "Window" show filename
    const Point Word_query_window::button_change_file_xy{ Point{0,0} };
    const Point Word_query_window::text_current_filename_xy{ Point{ button_change_file_xy.x + button_change_file_size_x, button_change_file_xy.y + button_change_file_size_y*9/10 } };

    // "Window" select
    const Point Word_query_window::button_occurences_xy{ Point{0, button_change_file_xy.y + button_change_file_size_y} };
    const Point Word_query_window::in_box_occurences_xy{ Point{button_occurences_xy.x + button_occurences_size_x,button_occurences_xy.y} };
    const Point Word_query_window::text_occurences_xy{ Point{in_box_occurences_xy.x + in_box_occurences_size_x,in_box_occurences_xy.y + in_box_occurences_size_y*9/10} };

    const Point Word_query_window::button_most_frequent_xy{ Point{0, button_occurences_xy.y + button_occurences_size_y} };

    const Point Word_query_window::button_longest_xy{ Point{0, button_most_frequent_xy.y + button_most_frequent_size_y} };

    const Point Word_query_window::button_shortest_xy{ Point{0, button_longest_xy.y + button_longest_size_y} };

    const Point Word_query_window::button_starting_with_xy{ Point{0, button_shortest_xy.y + button_shortest_size_y} };
    const Point Word_query_window::in_box_starting_with_xy{ Point{button_starting_with_xy.x + button_starting_with_size_x,button_starting_with_xy.y} };

    const Point Word_query_window::button_with_len_xy{ Point{0, button_starting_with_xy.y + button_starting_with_size_y} };
    const Point Word_query_window::in_box_with_len_xy{ Point{button_with_len_xy.x + button_with_len_size_x,button_with_len_xy.y} };

    const Point Word_query_window::button_show_all_xy{ Point{0, button_with_len_xy.y + button_with_len_size_y} };

    // "Window" display order
    const Point Word_query_window::button_display_back_xy{ Point{ 0 , window_size_y - button_display_back_size_y } };
    const Point Word_query_window::button_previous_page_xy{ Point{ window_size_x - button_previous_page_size_x - button_next_page_size_x, window_size_y - button_previous_page_size_y } };
    const Point Word_query_window::button_next_page_xy{ Point{ window_size_x - button_next_page_size_x, window_size_y - button_previous_page_size_y } };

    const Point Word_query_window::text_display_xy{ Point{0,window_offset_xy.y + text_current_filename_font_size } };

    Word_query_window::Word_query_window()
        :Window{ window_offset_xy, window_size_x, window_size_y, window_label },

        // Error
        text_error{ text_error_xy,"" },

        // "Window" open file
        in_box_filename{ in_box_filename_xy,in_box_filename_size_x,in_box_filename_size_y,in_box_filename_label },
        button_open_file{
            button_open_file_xy,button_open_file_size_x,button_open_file_size_y,button_open_file_label,
            [](Graph_lib::Address, Graph_lib::Address pw) { Graph_lib::reference_to<Word_query_window>(pw).button_open_file_event(); }
        },

        // all following Menus
        button_change_file{
            button_change_file_xy,button_change_file_size_x,button_change_file_size_y,button_change_file_label,
            [](Graph_lib::Address, Graph_lib::Address pw) { Graph_lib::reference_to<Word_query_window>(pw).button_change_file_event(); }
        },
        text_current_filename{ text_current_filename_xy,"" },

        // "Window" Select Option
        button_occurences{
            button_occurences_xy,button_occurences_size_x,button_occurences_size_y,button_occurences_label,
            [](Graph_lib::Address, Graph_lib::Address pw) { Graph_lib::reference_to<Word_query_window>(pw).button_occurences_event(); }
        },
        in_box_occurences{ in_box_occurences_xy,in_box_occurences_size_x,in_box_occurences_size_y,in_box_occurences_label },
        text_occurences{ text_occurences_xy,"" },

        button_most_frequent{
            button_most_frequent_xy,button_most_frequent_size_x,button_most_frequent_size_y,button_most_frequent_label,
            [](Graph_lib::Address, Graph_lib::Address pw) { Graph_lib::reference_to<Word_query_window>(pw).button_most_frequent_event(); }
        },

        button_longest{
            button_longest_xy,button_longest_size_x,button_longest_size_y,button_longest_label,
            [](Graph_lib::Address, Graph_lib::Address pw) { Graph_lib::reference_to<Word_query_window>(pw).button_longest_event(); }
        },

        button_shortest{
            button_shortest_xy,button_shortest_size_x,button_shortest_size_y,button_shortest_label,
            [](Graph_lib::Address, Graph_lib::Address pw) { Graph_lib::reference_to<Word_query_window>(pw).button_shortest_event(); }
        },

        button_starting_with{
            button_starting_with_xy,button_starting_with_size_x,button_starting_with_size_y,button_starting_with_label,
            [](Graph_lib::Address, Graph_lib::Address pw) { Graph_lib::reference_to<Word_query_window>(pw).button_starting_with_event(); }
        },
        in_box_starting_with{ in_box_starting_with_xy,in_box_starting_with_size_x,in_box_starting_with_size_y,in_box_starting_with_label },

        button_with_len{
            button_with_len_xy,button_with_len_size_x,button_with_len_size_y,button_with_len_label,
            [](Graph_lib::Address, Graph_lib::Address pw) { Graph_lib::reference_to<Word_query_window>(pw).button_with_len_event(); }
        },
        in_box_with_len{ in_box_with_len_xy,in_box_with_len_size_x,in_box_with_len_size_y,in_box_with_len_label },

        button_show_all{
            button_show_all_xy,button_show_all_size_x,button_show_all_size_y,button_show_all_label,
            [](Graph_lib::Address, Graph_lib::Address pw) { Graph_lib::reference_to<Word_query_window>(pw).button_show_all_event(); }
        },

        // "Window" display 
        button_display_back{
            button_display_back_xy,button_display_back_size_x,button_display_back_size_y,button_display_back_label,
            [](Graph_lib::Address, Graph_lib::Address pw) { Graph_lib::reference_to<Word_query_window>(pw).button_display_back_event(); }
        },
        button_previous_page{
            button_previous_page_xy,button_previous_page_size_x,button_previous_page_size_y,button_previous_page_label,
            [](Graph_lib::Address, Graph_lib::Address pw) { Graph_lib::reference_to<Word_query_window>(pw).button_previous_page_event(); }
        },
        button_next_page{
            button_next_page_xy,button_next_page_size_x,button_next_page_size_y,button_next_page_label,
            [](Graph_lib::Address, Graph_lib::Address pw) { Graph_lib::reference_to<Word_query_window>(pw).button_next_page_event(); }
        }
    {
        init_element(*this, text_error, text_error_font_size, text_error_color);

        init_window_open_file();
        init_window_show_filename();
        init_window_select();
        init_window_display();

        show_window_open_file();
    }

    void Word_query_window::init_window_open_file()
    {
        init_element(*this, in_box_filename, in_box_filename_text_size, in_box_filename_label_size);
        init_element(*this, button_open_file);
    }

    void Word_query_window::show_window_open_file()
    {
        in_box_filename.show();
        button_open_file.show();
    }

    void Word_query_window::hide_window_open_file()
    {
        in_box_filename.hide();
        button_open_file.hide();
    }

    void Word_query_window::init_window_show_filename()
    {
        init_element(*this, button_change_file);
        init_element(*this, text_current_filename, text_current_filename_font_size, text_current_filename_color);
    }

    void Word_query_window::show_window_show_filename()
    {
        button_change_file.show();
        text_current_filename.set_label(current_filename);
    }

    void Word_query_window::hide_window_show_filename()
    {
        button_change_file.hide();
        text_current_filename.set_label("");
    }

    void Word_query_window::init_window_select()
    {
        init_element(*this, button_occurences);
        init_element(*this, in_box_occurences, in_box_occurences_text_size, in_box_occurences_label_size);
        init_element(*this, text_occurences, text_occurences_font_size, text_occurences_color);

        init_element(*this, button_most_frequent);

        init_element(*this, button_longest);

        init_element(*this, button_shortest);

        init_element(*this, button_starting_with);
        init_element(*this, in_box_starting_with, in_box_starting_with_text_size, in_box_starting_with_label_size);

        init_element(*this, button_with_len);
        init_element(*this, in_box_with_len, in_box_with_len_text_size, in_box_with_len_label_size);

        init_element(*this, button_show_all);
    }

    void Word_query_window::show_window_select()
    {
        button_occurences.show();
        in_box_occurences.show();

        button_most_frequent.show();

        button_longest.show();

        button_shortest.show();

        button_starting_with.show();
        in_box_starting_with.show();

        button_with_len.show();
        in_box_with_len.show();

        button_show_all.show();
    }

    void Word_query_window::hide_window_select()
    {
        button_occurences.hide();
        in_box_occurences.empty();
        in_box_occurences.hide();
        text_occurences.set_label("");

        button_most_frequent.hide();

        button_longest.hide();

        button_shortest.hide();

        button_starting_with.hide();
        in_box_starting_with.empty();
        in_box_starting_with.hide();

        button_with_len.hide();
        in_box_with_len.empty();
        in_box_with_len.hide();

        button_show_all.hide();
    }

    void Word_query_window::init_window_display()
    {
        init_element(*this, button_display_back);
        init_element(*this, button_previous_page);
        init_element(*this, button_next_page);
    }

    void Word_query_window::show_window_display()
    {
        button_display_back.show();

        if (page != 0) {
            button_previous_page.show();
        }
        if (text_display.size() > text_display_entrys_per_page*(page + 1)) {
            button_next_page.show();
        }
    }

    void Word_query_window::hide_window_display()
    {
        button_display_back.hide();
        button_previous_page.hide();
        button_next_page.hide();
    }

    void Word_query_window::button_open_file_event()
    {
        text_error.set_label("");

        current_filename = in_box_filename.get_string();
        in_box_filename.empty();

        if (current_filename.empty()) {
            button_open_file.hide();        // to prevent button is still preselected
            button_open_file.show();
            text_error.set_label(text_error_label_invalid);
        }
        else if (!file_exists(current_filename)) {
            button_open_file.hide();        // to prevent button is still preselected
            button_open_file.show();
            text_error.set_label(text_error_label_no_file);
        }
        else {
            words_in_file = cleaned_words::read_words_from_file(current_filename);

            hide_window_open_file();
            show_window_show_filename();
            show_window_select();
        }
    }

    void Word_query_window::button_change_file_event()
    {
        hide_window_show_filename();
        hide_window_select();
        hide_window_display();

        show_window_open_file();
    }

    void Word_query_window::button_occurences_event()
    {
        unselect(button_occurences);

        auto search_word = in_box_occurences.get_string();
        in_box_occurences.empty();

        auto occurences = word_query::occurences_of_word(search_word, words_in_file);
        text_occurences.set_label(std::to_string(occurences));
    }

    void Word_query_window::button_most_frequent_event()
    {
        unselect(button_most_frequent);

        auto most_frequent_words = word_query::most_frequent_words(words_in_file);

        init_text_display(most_frequent_words);
        hide_window_select();
        show_window_display();
        print_page();
    }

    void Word_query_window::button_longest_event()
    {
        unselect(button_longest);

        auto longest_words = word_query::longest_words(words_in_file);

        init_text_display(longest_words);
        hide_window_select();
        show_window_display();
        print_page();
    }

    void Word_query_window::button_shortest_event()
    {
        unselect(button_shortest);

        auto shortest_words = word_query::shortest_words(words_in_file);

        init_text_display(shortest_words);
        hide_window_select();
        show_window_display();
        print_page();
    }

    void Word_query_window::button_starting_with_event()
    {
        unselect(button_starting_with);

        auto begin_str = in_box_starting_with.get_string();
        in_box_starting_with.empty();

        auto words_starting_with = word_query::words_starting_with(begin_str, words_in_file);

        init_text_display(words_starting_with);
        hide_window_select();
        show_window_display();
        print_page();
    }

    void Word_query_window::button_with_len_event()
    {
        unselect(button_with_len);

        auto length = in_box_with_len.get_int();
        in_box_with_len.empty();

        if (length > 0) {
            auto words_with_len = word_query::words_with_length(length, words_in_file);

            init_text_display(words_with_len);
            hide_window_select();
            show_window_display();
            print_page();
        }
    }

    void Word_query_window::button_show_all_event()
    {
        unselect(button_show_all);

        init_text_display(words_in_file);
        hide_window_select();
        show_window_display();
        print_page();
    }

    void Word_query_window::button_display_back_event()
    {
        for (int i = 0; i < text_display.size(); ++i) {
            detach(text_display[i]);
        }
        text_display.~Vector_ref();

        page = 0;

        hide_window_display();
        show_window_select();
    }

    void Word_query_window::button_previous_page_event()
    {
        --page;
        hide_window_display();
        show_window_display();
        print_page();
    }

    void Word_query_window::button_next_page_event()
    {
        ++page;
        hide_window_display();
        show_window_display();
        print_page();
    }

    void Word_query_window::print_page()
    {
        auto entrys_per_page = text_display_entrys_per_page;

        for (int i = 0; i < text_display.size(); ++i) {
            detach(text_display[i]);
        }

        for (int i = entrys_per_page * page; i < text_display.size() && i < entrys_per_page + (entrys_per_page*page); ++i) {
            text_display[i].set_font_size(text_display_font_size);
            text_display[i].set_color(text_display_color);
            attach(text_display[i]);
        }
    }

    int word_query_application()
    {
        Word_query_window win;
        return Graph_lib::gui_main();
    }
}

main.cpp

#include "Word_query_window.h"

int main()
{
    return word_query_gui::word_query_application();
}

Cleaned_words.h

#ifndef CLEAN_FILE290320180702_GUARD
#define CLEAN_FILE290320180702_GUARD

#include <cctype>
#include <string>
#include <vector>
#include <map>

namespace cleaned_words {

    using Word = std::string;
    using Occurences = int;

    std::map<Word, Occurences> read_words_from_file(const std::string& filename);
    std::map<Word, Occurences> read_cleaned_words_with_occurence(std::istream& is);
    bool contains_digits(const Word& word);
    Word remove_invalid_signs(Word word, const std::string& invalid_signs);

    inline bool unsigned_isspace(unsigned char c)
    {
        return std::isspace(c);
    }

    inline bool unsigned_isdigit(unsigned char c)
    {
        return std::isdigit(c);
    }

    Word remove_whitespace(Word word);
    Word remove_capital_letters(Word word);
    std::vector<Word> remove_contractions(const Word& word);
    void remove_plural(std::map<Word, Occurences>& cleaned_words);
    void write_cleaned_words_to_file(const std::string& filename, const std::map<Word, Occurences>& cleaned_words);
}
#endif

Cleaned_words.cpp

#include "Cleaned_words.h"

#include <algorithm>
#include <cctype>
#include <filesystem>
#include <fstream>


namespace cleaned_words {

    std::map<Word, Occurences> read_words_from_file(const std::string& filename)
    {
        std::ifstream ifs{ filename };
        if (!ifs) {
            throw std::runtime_error("void read_words_from_file(const std::string& filename)\nFile could not be opened\n");
        }
        return read_cleaned_words_with_occurence(ifs);
    }

    std::map<Word, Occurences> read_cleaned_words_with_occurence(std::istream& is)
    {
        std::map<Word, Occurences> cleaned_words;

        for (Word word; is >> word;) {

            if (contains_digits(word)) continue;

            word = remove_invalid_signs(word, R"(°-_^@{}[]<>&.,_()+-=?“”:;/\")");
            word = remove_whitespace(word);
            word = remove_capital_letters(word);

            if (word.empty()) continue;

            std::vector<Word> words = remove_contractions(word);

            for (auto& word : words) {  // remove ' after concatenations were run to not erase them to early
                word = remove_invalid_signs(word, "'");
            }

            for (const auto& word : words) {

                if (word.size() == 1 && word != "a" && word != "i" && word != "o") continue;

                ++cleaned_words[word];
            }
        }

        remove_plural(cleaned_words);

        return cleaned_words;
    }

    bool contains_digits(const Word& word)
    {
        if (word.empty()) return false;
        return std::any_of(word.begin(), word.end(), unsigned_isdigit);
    }

    Word remove_invalid_signs(Word word,const std::string& invalid_signs)
        // replace invalid signs with whitespace
    {
        auto is_invalid = [&](char c) { return invalid_signs.find(c) != std::string::npos; };
        word.erase(std::remove_if(word.begin(), word.end(), is_invalid), word.end());
        return word;
    }

    Word remove_whitespace(Word word)
    {
        if (word.empty()) return word;
        word.erase(std::remove_if(word.begin(), word.end(), unsigned_isspace), word.end());     
        return word;
    }

    Word remove_capital_letters(Word word)
    {
        for (auto& letter : word) {
            letter = std::tolower(static_cast<unsigned char>(letter));
        }
        return word;
    }

    std::vector<Word> remove_contractions(const Word& word)
    {
        const std::map<Word, std::vector<Word>> shorts_and_longs
        {
            { "aren't",{ "are","not" }},
            { "can't",  {"cannot"} },
            { "could've",{ "could","have" } },
            { "couldn't",{ "could","not" } },
            { "daresn't",{ "dare","not" } },
            { "dasn't",{ "dare","not" } },
            { "didn't",{ "did","not" } },
            { "doesn't",{ "does","not" } },
            { "don't",{ "do","not" } },
            { "e'er",{ "ever" } },
            { "everyone's",{ "everyone","is" } },
            { "finna",{ "fixing","to" } },
            { "gimme",{ "give","me" } },
            { "gonna",{ "going","to" } },
            { "gon't",{ "go","not" } },
            { "gotta",{ "got","to" } },
            { "hadn't",{ "had","not" } },
            { "hasn't",{ "has","not" } },
            { "haven't",{ "have","not" } },
            { "he've",{ "he","have" } },
            { "how'll",{ "how","will" } },
            { "how're",{ "how","are" } },
            { "I'm",{ "I","am" } },
            { "I'm'a",{ "I","am","about","to" } },
            { "I'm'o",{ "I","am","going","to" } },
            { "I've",{ "I","have" } },
            { "isn't",{ "is","not" } },
            { "it'd",{ "it","would" } },
            { "let's",{ "let","us" } },
            { "ma'am",{ "madam" } },
            { "mayn't",{ "may","not" } },
            { "may've",{ "may","have" } },
            { "mightn't",{ "might","not" } },
            { "might've",{ "might","have" } },
            { "mustn't",{ "must","not" } },
            { "mustn't've",{ "must","not","have" } },
            { "must've",{ "must","have" } },
            { "needn't",{ "need","not" } },
            { "ne'er",{ "never" } },
            { "o'clock",{ "of","the","clock" } },
            { "o'er",{ "over" } },
            { "ol'",{ "old" } },
            { "oughtn't",{ "ought","not" } },
            { "shan't",{ "shall","not" } },
            { "should've",{ "should","have" } },
            { "shouldn't",{ "should","not" } },
            { "that're",{ "that","are" } },
            { "there're",{ "there","are" } },
            { "these're",{ "these","are" } },
            { "they've",{ "they","have" } },
            { "those're",{ "those","are" } },
            { "'tis",{ "it","is" } },
            { "'twas",{ "it","was" } },
            { "wasn't",{ "was","not" } },
            { "we'd've",{ "we","would","have" } },
            { "we'll",{ "we","will" } },
            { "we're",{ "we","are" } },
            { "we've",{ "we","have" } },
            { "weren't",{ "were","not" } },
            { "what'd",{ "what","did" } },
            { "what're",{ "what","are" } },
            { "what've",{ "what","have" } },
            { "where'd",{ "where","did" } },
            { "where're",{ "where","are" } },
            { "where've",{ "where","have" } },
            { "who'd've",{ "who","would","have" } },
            { "who're",{ "who","are" } },
            { "who've",{ "who","have" } },
            { "why'd",{ "why","did" } },
            { "why're",{ "why","are" } },
            { "won't",{ "will","not" } },
            { "would've",{ "would","have" } },
            { "wouldn't",{ "would","not" } },
            { "y'all",{ "you","all" } },
            { "y'all'd've",{ "you","all","would","have" } },
            { "yesn't",{ "yes","not" } },
            { "you're",{ "you","are" } },
            { "you've",{ "you","have" } },
            { "whomst'd've",{ "whomst","would","have" } },
            { "noun's",{ "noun","is" } },
        };

        auto it = shorts_and_longs.find(word);

        if (it == shorts_and_longs.end()) {
            return std::vector<Word>{word};
        }
        else {
            return it->second;
        }

        return std::vector<Word>{};
    }

    void remove_plural(std::map<Word, Occurences>& cleaned_words)
        // assume a plural is a word with an additional s
        // e.g. ship and ships
        // if both are present ships gets deleted and ++ship
    {
        for (auto it = cleaned_words.begin(); it != cleaned_words.end();) {

            if(!it->first.empty() && it->first.back() == 's') {
                Word singular = it->first;
                singular.pop_back();    // remove 's' at the end

                auto it_singular = cleaned_words.find(singular);

                if (it_singular != cleaned_words.end()) {
                    cleaned_words[it_singular->first]+= it->second;
                    it = cleaned_words.erase(it);
                }
                else {
                    ++it;
                }
            }
            else {
                ++it;
            }
        }
    }

    void write_cleaned_words_to_file(const std::string& filename, const std::map<Word, Occurences>& cleaned_words)
    {
        std::ofstream ofs{ filename };

        for (const auto& word : cleaned_words) {
            ofs << word.first << " " << word.second << '\n';
        }
    }
}

Word_query.h

#ifndef WORD_QUERY_GUARD_270820181433
#define WORD_QUERY_GUARD_270820181433

#include <map>
#include <string>
#include <vector>

namespace word_query {
    using Word = std::string;
    using Occurences = int;
    using Length = std::map<Word, Occurences>::size_type;

    int occurences_of_word(const Word& word, const std::map<Word, Occurences>& words_with_occurences);
    std::vector<std::pair<Word, Occurences>> most_frequent_words(const std::map<Word, Occurences>& words_with_occurences);
    std::vector<Word> longest_words(const std::map<Word, Occurences>& words_with_occurences);
    std::vector<Word> shortest_words(const std::map<Word, Occurences>& words_with_occurences);
    std::vector<Word> words_starting_with(const Word& begin_of_word, const std::map<Word, Occurences>& words_with_occurences);
    std::vector<Word> words_with_length(Length length, const std::map<Word, Occurences>& words_with_occurences);
}
#endif

Word_query.cpp

#include "Word_query.h"

#include <algorithm>

namespace word_query {

    int occurences_of_word(const Word& word, const std::map<Word, Occurences>& words_with_occurences)
        //How many occurences of x are there in a file? 
    {
        auto it = words_with_occurences.find(word);

        if (it == words_with_occurences.end()) {
            return 0;
        }
        else {
            return it->second;
        }
    }

    std::vector<std::pair<Word, Occurences>> most_frequent_words(const std::map<Word, Occurences>& words_with_occurences)
        //Which word occurs most frequently?
    {
        using pair_type = std::map<Word, Occurences>::value_type;

        std::vector<std::pair<Word, Occurences>> words;

        auto it_begin = words_with_occurences.begin();
        auto it_result = words_with_occurences.end();
        auto it_last_result = words_with_occurences.end();

        for(;;){
            it_result = std::max_element(
                it_begin, words_with_occurences.end(),
                [](const pair_type a, const pair_type b)
                {
                    return a.second < b.second;
                }
            );

            if (it_result == words_with_occurences.end()) {
                break;
            }
            else if (it_last_result == words_with_occurences.end() ||  it_last_result->second == it_result->second) {
                words.push_back(*it_result);
            }
            else {
                break;
            }

            it_last_result = it_result;
            it_begin = ++it_result;
        } 
        return words;
    }

    std::vector<Word> longest_words(const std::map<Word, Occurences>& words_with_occurences)
        //Which is the longest word in the file?
    {
        using pair_type = std::map<Word, Occurences>::value_type;

        std::vector<Word> words;

        auto it_begin = words_with_occurences.begin();
        auto it_result = words_with_occurences.end();
        auto it_last_result = words_with_occurences.end();

        for (;;) {
            it_result = std::max_element(
                it_begin, words_with_occurences.end(),
                [](const pair_type a, const pair_type b)
                {
                    return a.first.size() < b.first.size();
                }
            );

            if (it_result == words_with_occurences.end()) {
                break;
            }
            else if (it_last_result == words_with_occurences.end() || it_last_result->first.size() == it_result->first.size()) {
                words.push_back(it_result->first);
            }
            else {
                break;
            }

            it_last_result = it_result;
            it_begin = ++it_result;
        }
        return words;
    }

    std::vector<Word> shortest_words(const std::map<Word, Occurences>& words_with_occurences)
        //Which is the shortest word in the file?
    {
        using pair_type = std::map<Word, Occurences>::value_type;

        std::vector<Word> words;

        auto it_begin = words_with_occurences.begin();
        auto it_result = words_with_occurences.end();
        auto it_last_result = words_with_occurences.end();

        for (;;) {
            it_result = std::min_element(
                it_begin, words_with_occurences.end(),
                [](const pair_type a, const pair_type b)
                {
                    return a.first.size() < b.first.size();
                }
            );

            if (it_result == words_with_occurences.end()) {
                break;
            }
            else if (it_last_result == words_with_occurences.end() || it_last_result->first.size() == it_result->first.size()) {
                words.push_back(it_result->first);
            }
            else {
                break;
            }

            it_last_result = it_result;
            it_begin = ++it_result;
        }
        return words;
    }

    std::vector<Word> words_starting_with(const Word& begin_of_word, const std::map<Word, Occurences>& words_with_occurences)
    {
        std::vector<Word> matched_words;

        for (const auto& word : words_with_occurences) {
            if (word.first.substr(0, begin_of_word.size()) == begin_of_word) {
                matched_words.push_back(word.first);
            }
        }
        return matched_words;
    }

    std::vector<Word> words_with_length(Length length, const std::map<Word, Occurences>& words_with_occurences)
        //all words with n letters
    {
        std::vector<Word> words;

        for (const auto& element : words_with_occurences) {
            if (element.first.size() == length)
                words.push_back(element.first);
        }
        return words;
    }
}

Point.h

// This is a GUI support code to the chapters 12-16 of the book
// "Programming -- Principles and Practice Using C++" by Bjarne Stroustrup
//
#ifndef POINT_GUARD
#define POINT_GUARD

struct Point {
    int x, y;
    Point(int xx, int yy) : x(xx), y(yy) { }
    Point() :x(0), y(0) { }
};

inline bool operator==(Point a, Point b) { return a.x==b.x && a.y==b.y; } 
inline bool operator!=(Point a, Point b) { return !(a==b); }
#endif // POINT_GUARD

GUI.h

//
// This is a GUI support code to the chapters 12-16 of the book
// "Programming -- Principles and Practice Using C++" by Bjarne Stroustrup
//

#ifndef GUI_GUARD
#define GUI_GUARD

#include "Window.h"
#include "Graph.h"

#include <string>

namespace Graph_lib {

    //------------------------------------------------------------------------------

    typedef void* Address;    // Address is a synonym for void*
    typedef void(*Callback)(Address, Address);    // FLTK's required function type for all callbacks

                                                  //------------------------------------------------------------------------------

    template<class W> W& reference_to(Address pw)
        // treat an address as a reference to a W
    {
        return *static_cast<W*>(pw);
    }

    //------------------------------------------------------------------------------

    class Widget {
        // Widget is a handle to an Fl_widget - it is *not* an Fl_widget
        // We try to keep our interface classes at arm's length from FLTK
    public:
        Widget(Point xy, int w, int h, const std::string& s, Callback cb)
            : loc(xy), width(w), height(h), label(s), do_it(cb)
        {}

        virtual void move(int dx, int dy) { hide(); pw->position(loc.x += dx, loc.y += dy); show(); }
        virtual void hide() { pw->hide(); }
        virtual void show() { pw->show(); }
        virtual void attach(Graph_lib::Window&) = 0;

        Point loc;
        int width;
        int height;
        std::string label;
        Callback do_it;

        virtual ~Widget() { }

    protected:
        Graph_lib::Window* own;    // every Widget belongs to a Window
        Fl_Widget* pw;  // connection to the FLTK Widget
    private:
        Widget & operator=(const Widget&); // don't copy Widgets
        Widget(const Widget&);
    };

    //------------------------------------------------------------------------------

    struct Button : Widget {
        Button(Point xy, int w, int h, const std::string& label, Callback cb)
            : Widget(xy, w, h, label, cb)
        {}

        void attach(Graph_lib::Window&);
    };

    //------------------------------------------------------------------------------

    struct In_box : Widget {
        In_box(Point xy, int w, int h, const std::string& s)
            :Widget(xy, w, h, s, 0) { }
        int get_int();
        std::string get_string();

        void attach(Graph_lib::Window& win);

        // Extensions not provided by Stroustrup:
        void set_text_size(int size);
        void set_label_size(int size);

        void empty();   // emptys the input field
    };

    //------------------------------------------------------------------------------

    struct Out_box : Widget {
        Out_box(Point xy, int w, int h, const std::string& s)
            :Widget(xy, w, h, s, 0) { }
        void put(int);
        void put(const std::string&);

        void attach(Graph_lib::Window& win);

        // Extensions not provided by Stroustrup:
        void set_text_size(int size);
        void set_label_size(int size);
    };

    //------------------------------------------------------------------------------

    struct Menu : Widget {
        enum Kind { horizontal, vertical };
        Menu(Point xy, int w, int h, Kind kk, const std::string& label)
            : Widget(xy, w, h, label, 0), k(kk), offset(0)
        {
        }

        Vector_ref<Button> selection;
        Kind k;
        int offset;
        int attach(Button& b);      // Menu does not delete &b
        int attach(Button* p);      // Menu deletes p

        void show()                 // show all buttons
        {
            for (auto i = 0; i<selection.size(); ++i)
                selection[i].show();
        }
        void hide()                 // hide all buttons
        {
            for (auto  i = 0; i<selection.size(); ++i)
                selection[i].hide();
        }
        void move(int dx, int dy)   // move all buttons
        {
            for (auto  i = 0; i<selection.size(); ++i)
                selection[i].move(dx, dy);
        }

        void attach(Graph_lib::Window& win)    // attach all buttons
        {
            for (int i = 0; i < selection.size(); ++i) {
                win.attach(selection[i]);
            }
            own = &win;
        }

    };

    //------------------------------------------------------------------------------

} // of namespace Graph_lib

#endif // GUI_GUARD

GUI.cpp

#include "GUI.h"
#include <sstream>

using namespace Graph_lib;


void Button::attach(Graph_lib::Window& win)
{
    pw = new Fl_Button(loc.x, loc.y, width, height, label.c_str());
    pw->callback(reinterpret_cast<Fl_Callback*>(do_it), &win); // pass the window
    own = &win;
}

int In_box::get_int()
{
    Fl_Input& pi = reference_to<Fl_Input>(pw);
    //  return atoi(pi.value());
    const char* p = pi.value();
    if (!isdigit(p[0])) return -999999;
    return atoi(p);
}

std::string In_box::get_string()
{
    Fl_Input& pi = reference_to<Fl_Input>(pw);
    return std::string(pi.value());
}

void In_box::attach(Graph_lib::Window& win)
{
    pw = new Fl_Input(loc.x, loc.y, width, height, label.c_str());
    own = &win;
}

void In_box::set_text_size(int size)
{
    reference_to<Fl_Input>(pw).textsize(size);
}

void In_box::set_label_size(int size)
{
    reference_to<Fl_Input>(pw).labelsize(size);
}

void In_box::empty()    // emptys the input field
{
    reference_to<Fl_Input>(pw).value("");
}

void Out_box::put(int i)
{
    Fl_Output& po = reference_to<Fl_Output>(pw);
    std::stringstream ss;
    ss << i;

    po.value(ss.str().c_str());
}

void Out_box::put(const std::string& s)
{
    reference_to<Fl_Output>(pw).value(s.c_str());
}

void Out_box::attach(Graph_lib::Window& win)
{
    pw = new Fl_Output(loc.x, loc.y, width, height, label.c_str());
    own = &win;
}

void Out_box::set_text_size(int size)
{
    reference_to<Fl_Output>(pw).textsize(size);
}

void Out_box::set_label_size(int size)
{
    reference_to<Fl_Output>(pw).labelsize(size);
}

int Menu::attach(Button& b)
{
    b.width = width;
    b.height = height;

    switch (k) {
    case horizontal:
        b.loc = Point(loc.x + offset, loc.y);
        offset += b.width;
        break;
    case vertical:
        b.loc = Point(loc.x, loc.y + offset);
        offset += b.height;
        break;
    }
    selection.push_back(&b);
    return int(selection.size() - 1);
}

int Menu::attach(Button* p)
{
    //  owned.push_back(p);
    return attach(*p);
}

Window.h

#include "FL/fl_draw.H"
#include "FL/Enumerations.H"

#include "Fl/Fl_JPEG_Image.H"
#include "Fl/Fl_GIF_Image.H"

#include "Point.h"

#include <string>
#include <vector>

namespace Graph_lib {

    class Shape;    // "forward declare" Shape
    class Widget;

    class Window : public Fl_Window {
    public:
        Window(int w, int h, const std::string& title);         // let the system pick the location
        Window(Point xy, int w, int h, const std::string& title);   // top left corner in xy
        virtual ~Window() { }

        int x_max() const { return w; }
        int y_max() const { return h; }

        void resize(int ww, int hh) { w = ww, h = hh; size(ww, hh); }

        void set_label(const std::string& s) { label(s.c_str()); }

        void attach(Shape& s);
        void attach(Widget& w);

        void detach(Shape& s);  // remove s from shapes 
        void detach(Widget& w); // remove w from window (deactivate callbacks)

        void put_on_top(Shape& p);  // put p on top of other shapes

    protected:
        void draw();

    private:
        std::vector<Shape*> shapes; // shapes attached to window
        int w, h;                   // window size

        void init();
    };

    int gui_main(); // invoke GUI library's main event loop

    inline int x_max() { return Fl::w(); }  // width of screen in pixels
    inline int y_max() { return Fl::h(); }  // height of screen in pixels

}
#endif

Window.cpp

#include "Window.h"
#include "Graph.h"
#include "GUI.h"

namespace Graph_lib {

    Window::Window(int ww, int hh, const std::string& title)
        :Fl_Window(ww, hh, title.c_str()), w(ww), h(hh)
    {
        init();
    }

    Window::Window(Point xy, int ww, int hh, const std::string& title)
        : Fl_Window(xy.x, xy.y, ww, hh, title.c_str()), w(ww), h(hh)
    {
        init();
    }

    void Window::init()
    {
        resizable(this);
        show();
    }

    //---------------------------------------------------- 

    void Window::draw()
    {
        Fl_Window::draw();
        for (unsigned int i = 0; i<shapes.size(); ++i) shapes[i]->draw();
    }

    void Window::attach(Widget& w)
    {
        begin();            // FTLK: begin attaching new Fl_Wigets to this window
        w.attach(*this);    // let the Widget create its Fl_Wigits
        end();              // FTLK: stop attaching new Fl_Wigets to this window
    }

    void Window::detach(Widget& b)
    {
        b.hide();
    }

    void Window::attach(Shape& s)
    {
        shapes.push_back(&s);
        //      s.attached = this;
    }
    void Window::detach(Shape& s)
    {
        for (unsigned int i = shapes.size(); 0<i; --i)  // guess last attached will be first released
            if (shapes[i - 1] == &s)
                shapes.erase(shapes.begin() + (i - 1));//&shapes[i-1]);
    }


    void Window::put_on_top(Shape& p) {
        for (auto i = 0; i<shapes.size(); ++i) {
            if (&p == shapes[i]) {
                for (++i; i<shapes.size(); ++i)
                    shapes[i - 1] = shapes[i];
                shapes[shapes.size() - 1] = &p;
                return;
            }
        }
    }

    int gui_main() { return Fl::run(); }

} // Graph

Graph.h/cpp

Due to limit of the characters per post i can't post Graph.h / cpp complete. You can find it here if necessary to look into: http://www.stroustrup.com/Programming/PPP2code/

\$\endgroup\$
3
\$\begingroup\$

Classes

There are a few things you can do to simplify:

std::vector<std::pair<Word, Occurences>> most_frequent_words(const std::map<Word, Occurences>& words_with_occurences);
std::vector<Word> longest_words(const std::map<Word, Occurences>& words_with_occurences);
std::vector<Word> shortest_words(const std::map<Word, Occurences>& words_with_occurences);

First, I want to pay attention to:

std::vector<std::pair<Word, Occurences>> most_frequent_words(const std::map<Word, Occurences>& words_with_occurences);

in particular. Are you trying to return a list of the most frequent words? Or are you trying to return the most frequent words and their frequency? I would consider separating into two functions: a function that, given a particular word, retrieves the number of occurrences of that word, and one that simply gets a list of the most frequent words.

There are some caveats to this (regarding efficiency). Now, let's think about something more important. You always pass: const std::map<Word, Occurences>& words_with_occurences into each function. Seems kind of repetitive.

The initial temptation is to create a global variable called words_with_occurences that most_frequent_words, longest_words and shortest_words use instead of the parameter you have suggested, but as it has been said multiple times, global variables are bad. Class members are not though!

I am rather surprised you have not used a class, so I am uncertain if you have any exposure to classes. I am not entirely sure what a good C++ tutorial for classes is but maybe someone else can help with that.

Once you acquire a basic understanding of classes the outline is as follows:

  1. Create a class call it something like Ngram. This class is responsible for handling data related to word count and frequency.
  2. In the constructor, create words_with_occurrences member that can be later referred to by other methods.
  3. Now you can define the most_frequent_words longest_words and shortest_words without the words_with_occurrences parameter you have supplied.
  4. Any Ngram object should have an initialization parameter that specifies the data source to generate words_with_occurrences from.

FLUID

Creating a GUI can be annoying, there are often multiple ways to assist with the creation of a GUI. Often, even if a GUI is built on top of a language, there is another language/language extension/tool that helps actually create the GUI.

For instance, developing and iPhone app you have Swift or Objective-C as the "underlying language" and a tool like Interface Builder. Android has a similar set of tools. Developing on the web, roughly speaking, you have HTML for structuring the contents of the code, CSS for styling, and Javascript as the "underlying language".

It is a little difficult express exactly what I mean by "underlying language". In the case of HTML/CSS/JavaScript, HTML and CSS are not used for heavy computation, nor or they often used for dynamically generating content. Javascript on the other hand is.

In the case of FLTK, FLUID takes a similar role to (at least) HTML and, in many cases, be used over C++ to describe the static parts of your user interface. The parts of your GUI that are static (don't change) should probably be designed with FLUID, it will vastly simplify much of your code.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.