[C++] 154 マルチバイト文字有無の判定 コード改良の試み mbstowcs関数

[M1 Mac, Big Sur 11.6.8, clang 13.0.0, FLTK 1.3.8, NO IDE]

前回の続きです。

どうしても気になったので、さらに調べてみました。

どうやらappファイルではmbstowcs関数がまともに動かないようです。マルチバイト文字を1文字としてカウントすることができません。

下図の右ウインドウに表示されているように、#FFFFFF(#は3バイト文字)がstring、wstringともに10文字としてカウントされています。mbstowcs関数が機能していればwstringは8文字になるはずです。同時にビルドした実行ファイルでは実際そうなっています。

これはライブラリを提供しているApple側の問題に思えます。これで一応の結論にたどり着きました。

MacOSでC++を扱っていると細かいところで非対応や不具合に遭遇します。やはりWindowsのVisual C++が至高だと思います。まあいざとなればObjective-C++へ鞍替えします。

int narrowToWide(string str) {
	wchar_t *wcs = new wchar_t[str.length() + 1];
	int num = mbstowcs(wcs, str.c_str(), str.length() + 1);
    
	return num;
}

int multibyteDetect(string str){
    int length = str.length();
    cout << "length " << length << endl;
    output_line2->insert("length ");
    output_line2->insert((to_string(length)).c_str());
    output_line2->insert("\n");

    int length_w = narrowToWide(str);
    cout << "length_w " << length_w << endl;
    output_line2->insert("length_w ");
    output_line2->insert((to_string(length_w)).c_str());
    output_line2->insert("\n");

    if (length != length_w){
        return -1;
    }
    
    return 0;
}

[C++] 153 マルチバイト文字有無の判定 コード改良の試み

[M1 Mac, Big Sur 11.6.8, clang 13.0.0, FLTK 1.3.8, NO IDE]

前回の続きです。

そう言えば、ちょうど1ヶ月前にマルチバイト文字の抽出方法について記事を書いていました。その内容を流用します。

stringをwstringに変換して文字数を取得すれば、マルチバイト文字を1文字扱いにした全文字数+αが分かります。

これで文字列が可変長でも対応できるはずですが、自製カラーアプリのappファイルが落ちるようになってしまったため、前回のコードのままにしておきます。なおコンソール付きの実行ファイルでは問題なく動作します。

マルチバイト文字にあまり関わると深みにはまってしまうので、これ以上追究するのはやめておきます。

wstring narrowToWide(const string src) {
    wchar_t *wcs = new wchar_t[src.length() + 1];
    mbstowcs(wcs, src.c_str(), src.length() + 1);
    return wcs;
}

int multibyteDetect(string str){
    int length = str.length();
    cout << "length " << length << endl;

    wstring str_w = narrowToWide(str);
    int length_w = str_w.length();
    cout << "length_w " << length_w << endl;

    // stringの内容確認
    int i = 0;
    for (int b: str){
        cout << "string " << i << " " << b << endl;
        i++;
    }

    // stringの内容確認2
    for (int i = 0 ; i < str.length() ; ++i){
        cout << "string2 " << i << " " << str[i] << endl;
    }

    // wstringの内容確認
    int i2 = 0;
    for (int b: str_w){
        cout << "wstring " << i2 << " " << b << endl;
        i2++;
    }

    // wstringの内容確認2
    for (int i = 0 ; i < str_w.length() ; ++i){
        cout << "wstring2 " << i << " " << str_w[i] << endl;
    }

    if (length != length_w){
        return -1;
    }
    
    return 0;
}
--------------------------------------------------
出力例 #FFFFFF 数学記号の#(ここでの表記は1バイト文字の#)
--------------------------------------------------
length 10
length_w 8

string 0 35
string 1 -30
string 2 -128
string 3 -83
string 4 70
string 5 70
string 6 70
string 7 70
string 8 70
string 9 70

string2 0 #
string2 1 ?
string2 2 ?
string2 3 ?
string2 4 F
string2 5 F
string2 6 F
string2 7 F
string2 8 F
string2 9 F

wstring 0 35
wstring 1 8237
wstring 2 70
wstring 3 70
wstring 4 70
wstring 5 70
wstring 6 70
wstring 7 70

wstring2 0 35
wstring2 1 8237
wstring2 2 70
wstring2 3 70
wstring2 4 70
wstring2 5 70
wstring2 6 70
wstring2 7 70

[C++] 152 マルチバイト文字有無の判定

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

HTMLやCSSではカラーコードは#を先頭に付けます。

ただ、この#が曲者で1バイト文字、3バイト文字(数学記号)、3バイト文字(全角)の3種類あります。

ネット初心者以外ではまずないとは思いますが、後2者が混ざり込んでいるのに気が付かずネットに貼ってしまう方がいたりします。全角の場合は見れば分かるものの、数学記号の方は見た目が全く同じで厄介です。

そのようなカラーコードをアプリにコピペした際、不具合が生じないようにするため合計バイト数が7である場合のみ処理を進めるようにしました。

文字列が可変長の場合については調査中です。

ネットから#を含む文字列をコピペする場合はそのようなリスクがあることを知っておくべきでしょうね。

int multibyteDetect(string str){
    int length = str.length();
    cout << "length " << length << endl;

    if (length != 7){
        return -1;
    }
    return 0;
}