[C++] 90 10進数から16進数へ変換、大文字へ変換

[M1 Mac, Big Sur 11.6.7, clang 13.0.0, NO IDE]

C++で整数を変換するのは初めてかもしれません。大文字へ変換する関数も載せておきます。

C言語とC++のtoupper関数の違いが分からなくて苦労しました。今回はC言語の方を使っています。C++のtoupper関数は上級者向けでしょうか。型推論が効かないため正確に使わないとコンパイラからのダメ出しが止まりません。

またvectorの範囲コンストラクタというものを初めて使いましたが、最初見た時は関数なのか変数なのか文法的に矛盾しているように見えて意味が分かりませんでした。

現時点でアプリのサイズは455KBです。フル機能のJava版は45.6MBですから100分の1に収まっています。起動はもっさりから爆速になりました。実質的リファクタリングの効果もあると思います。

#include <algorithm>

using std::transform; using std::toupper;

// 大文字へ変換する関数
string capitalizeString(string s)
{
    vector<char> s_char(s.begin(), s.end());

    vector<char> s_char_up;
    for (auto && c:s_char){
        char c_up = toupper(c);
        s_char_up.push_back(c_up);
    }

    string str(s_char_up.begin(), s_char_up.end());

    return str;
}

int red = stoi(red0);
int green = stoi(green0);
int blue = stoi(blue0);

// 10進数から16進数へ変換
std::stringstream ss1;
ss1 << std::hex << red;
// 0埋めで2桁にする場合
// ss1 << std::hex << std::setw(2) << std::setfill('0') << red;
string red_hex = ss1.str();
cout << red_hex.c_str() << endl;

std::stringstream ss2;
ss2 << std::hex << green;
string green_hex = ss2.str();
cout << green_hex.c_str() << endl;

std::stringstream ss3;
ss3 << std::hex << blue;
string blue_hex = ss3.str();
cout << blue_hex.c_str() << endl;

// 大文字へ変換
string color_hex0 = red_hex + green_hex + blue_hex;
string color_hex = capitalizeString(color_hex0);
string color_zero = "0x" + color_hex;
code_input->value("");
code_input->insert(color_zero.c_str());
--------------------------------------------------
出力例
--------------------------------------------------
0xC9171E

[C++] 89 FLTK : ウィジェットの再描画 redraw関数

[M1 Mac, Big Sur 11.6.7, clang 13.0.0, NO IDE]

カラーボタンから取得したカラーコードをFl_Boxの色設定に使いました。redraw関数による再描画が必要になります。

extern Fl_Input *name_input, *romaji_input, *code_input;
extern Fl_Tabs *tabs;
extern string colorList[3][140];
extern string colorList2[4][3][120];
extern vector<string> tab_names;
extern Fl_Box *colorBox;
string *name, *romaji, *color;
const char *name_c, *romaji_c, *color_c;

vector<int> RGBConvert(string colorcode){
    vector<int> RGBColor;

    string red0 = colorcode.substr(2,2);
    int red = stoi(red0, nullptr, 16);
    RGBColor.push_back(red);

    string green0 = colorcode.substr(4,2);
    int green = stoi(green0, nullptr, 16);
    RGBColor.push_back(green);

    string blue0 = colorcode.substr(6,2);
    int blue = stoi(blue0, nullptr, 16);
    RGBColor.push_back(blue);

    return RGBColor;
}

void getColor(Fl_Widget*, long num){
    cout << "num " << num << endl;

    Fl_Widget * tab = tabs->value();
    const char* lbl = tab->label();
    cout << "lbl " << lbl << endl;
    string lbl_str = (string)lbl;

    int tab_num = getIndex(tab_names,lbl_str);
    cout << "tab_num " << tab_num << endl;

    if (tab_num == 0){
        name = &(colorList[0][num]);
        name_c = name->c_str();

        romaji_c = "-";

        color = &(colorList[2][num]);
        color_c = color->c_str();
        
    } else {
        name = &(colorList2[tab_num-1][0][num]);
        name_c = name->c_str();

        romaji = &(colorList2[tab_num-1][1][num]);
        romaji_c = romaji->c_str();
        
        color = &(colorList2[tab_num-1][2][num]);
        color_c = color->c_str();
        
    }
    name_input->value("");
    name_input->insert(name_c);

    romaji_input->value("");
    romaji_input->insert(romaji_c);

    code_input->value("");
    code_input->insert(color_c);

    vector<int> rgbcolor = RGBConvert(*color);
    int red = rgbcolor[0];
    int green = rgbcolor[1];
    int blue = rgbcolor[2];
    cout << "RGB " << red << " " << green << " " << blue <<endl;

    colorBox->redraw();
    colorBox->color(fl_rgb_color(red,green,blue));
}

[C++] 88 FLTK : Fl_Tabsのインデックス値取得

[M1 Mac, Big Sur 11.6.7, clang 13.0.0, NO IDE]

Fl_Tabsのインデックス値を取得し、押下したカラーボタンの内容を3次元配列データから取り出すようにしました。

Tabのインデックス値取得はfor文内で変数に代入する方法ではうまくいかず、関数の戻り値にするとあっさり出来ました。

ようやく次の段階に移ることができます。選択した色の表示、カラーコードの変換などです。

extern Fl_Tabs *tabs;
extern string colorList[3][140];
extern string colorList2[4][3][120];
extern vector<string> tab_names;

int getIndex(vector<string> &input, string searched) {
    for (int i = 0; i < input.size(); i++) {
        if (input[i] == searched) {
            return i;
        }
    }
    return -1;
}

void getColor(Fl_Widget*, long num){
    cout << "num " << num << endl;

    Fl_Widget * tab = tabs->value();
    const char* lbl = tab->label();
    cout << "lbl " << lbl << endl;
    string lbl_str = (string)lbl;

    int tab_num = getIndex(tab_names,lbl_str);
    cout << "tab_num " << tab_num << endl;

    if (tab_num == 0){
        string* name = &(colorList[0][num]);
        const char* name_c = name->c_str();
        name_input->value("");
        name_input->insert(name_c);

        const char* romaji_c = "-";
        romaji_input->value("");
        romaji_input->insert(romaji_c);

        string* color = &(colorList[2][num]);
        const char* color_c = color->c_str();
        code_input->value("");
        code_input->insert(color_c);

    } else {
        string* name = &(colorList2[tab_num-1][0][num]);
        const char* name_c = name->c_str();
        name_input->value("");
        name_input->insert(name_c);

        string* romaji = &(colorList2[tab_num-1][1][num]);
        const char* romaji_c = romaji->c_str();
        romaji_input->value("");
        romaji_input->insert(romaji_c);

        string* color = &(colorList2[tab_num-1][2][num]);
        const char* color_c = color->c_str();
        code_input->value("");
        code_input->insert(color_c);
    }
}

[C++] 87 FLTK : 長整数型を引数とするcallback関数

[M1 Mac, Big Sur 11.6.7, clang 13.0.0, NO IDE]

for文で一気に作成するButtonのcallback関数の書き方で難航しました。左側Tab内のButtonを押して、色名やカラーコードなどその内容を右上のFl_inputに表示します。

Fl_Callback1(Fl_Widget *, long)という長整数型データを第2引数とするcallback関数を使うことで解決しました。第2引数としてButtonのインデックス(通し番号)を設定しています。

今回は有りもので何とかなりましたが、Fl_Callbackを継承すれば好きなデータ型で独自のクラスを作れるでしょう。

Java(Swing)の場合はfor文の中でActionListenerを使えたものの、さすがにFLTKではcallback関数の定義をfor文内に埋め込みできず、加えてButtonのラベルをうまく取得できなくてさすがに詰んだのではないかと一時は諦めかけました。

最大の難関をクリアできたので、後は何とかなると思います。

void getColor(Fl_Widget*, long num){
    cout << "num " << num << endl;

    Fl_Widget* tab = tabs->value(); // 有効なタブのポインタ
    const char* lbl = tab->label(); // タブのラベル
    cout << "lbl " << lbl << endl;
    string lbl_str = (string)lbl;

    if (lbl_str == tab_names[0]){
        string* color_name = &(colorList[0][num]);
        const char* color_name_p = color_name->c_str();
        name_input->insert(color_name_p);
    } 
}

<中略>

button->callback(getColor,(long)num);