ようやくC++版の自作エディタも折り返しと矩形選択以外の機能の実装がだいたい終わりました。あとは細かな修正と動作確認です。
細かい修正の中に文字列をダブルクリックして文字列を選択する処理があります。よくある処理ですね。クリックした文字列の文字種と同じ文字種の範囲を選択する処理です。
文字種には平仮名、カタカナ、英字、数字、記号などなどがあります。クリックした文字種で前後の文字がどこまで同じかの判断が必要になるのですが、普通に実装するとこんな感じになると思います。
- クリックした文字の種類を判断する
- 文字列の前後で同じ文字の最小と最大インデックスを取得する
今回は関数の戻り値に関数を利用して判断する方法を紹介します。
通常の実装方法
クリックされた文字の種類に応じて前後どこまで同じか判断するようにした処理です。
// 平仮名判断関数
bool IsHiragana(wchar_t wc) {
if (0x3041 <= wc && wc <= 0x309f) {
return true;
} else {
return false;
}
}
// 片仮名判断関数
bool IsKatakana(wchar_t wc) {
if (0x30a0 <= wc && wc <= 0x30ff) {
return true;
} else {
return false;
}
}
// 文字の種類の定数
int HIRAGANA = 0;
int KATAKANA = 1;
int ALPHABET = 2;
// 文字の種類を取得する関数
int GetMojishu(wchar_t wc) {
if(IsHiragana(wc)) return HIRAGANA;
if(IsKatakana(wc)) return KATAKANA;
if(IsAlphabet(wc)) return ALPHABET;
:
}
// 文字列選択関数
void SetSelectionRange() {
// 1.文字種を取得する
int mojishu = GetMojishu(L'a');
// 2.文字種がどこまでかを判断する(文字種が増えると修正する必要がある)
for (int i= x; i< text.length(); i++){
if(mojishu == HIRAGANA){
if(IsHiragana(text.at(i))){
:
}
} else if(mojIshu == KATAKANA) {
if(IsKatakana(text.at(i))){
:
}
}
}
}
これでも全然問題ないのですが、この場合、文字種が増えると 2.の処理も修正する必要があります。そこで、1.の文字種返す関数を定数では無く、2.で実行する関数を返すようにします。こうすることで、2.の処理で分岐が不要になります。
関数の戻り値に関数を利用する方法
std::function で関数を返すようにします。std::function<bool(wchar_t wc)> が戻す関数の定義です。戻す関数の型と同じにします。
// 平仮名判断関数
bool IsHiragana(wchar_t wc) {
if (0x3041 <= wc && wc <= 0x309f) {
return true;
} else {
return false;
}
}
// 片仮名判断関数
bool IsKatakana(wchar_t wc) {
if (0x30a0 <= wc && wc <= 0x30ff) {
return true;
} else {
return false;
}
}
// 文字の種類の定数
int HIRAGANA = 0;
int KATAKANA = 1;
int ALPHABET = 2;
// 文字の種類を取得する関数
int GetMojishu(wchar_t wc) {
if(IsHiragana(wc)) return HIRAGANA;
if(IsKatakana(wc)) return KATAKANA;
if(IsAlphabet(wc)) return ALPHABET;
:
}
// 文字列選択関数
void SetSelectionRange() {
// 1.文字種を取得する
int mojishu = GetMojishu(L'a');
// 2.文字種がどこまでかを判断する(文字種が増えると修正する必要がある)
for (int i= x; i< text.length(); i++){
if(mojishu == HIRAGANA){
if(IsHiragana(text.at(i))){
:
}
} else if(mojIshu == KATAKANA) {
if(IsKatakana(text.at(i))){
:
}
}
}
}
おわりに
std::function を利用すると関数を戻すことができます。これで仮に文字種が増えても最小範囲の修正で済みますね。
コメント