Тема: Дуже сумна балада про string і українську абетку

Мені треба було отримати останню літеру зі змішаного рядка (українська абетка + цифри + деякі друковані символи).
Тому я наївно припустив, що метод back() із цим цілком впорається.
А виявилося, що він повертає останній байт, а не останню літеру.
Якщо це латинська абетка, то літера має 1 байт і все працює як слід. Якщо українська, 2 байти, ви отримаєте якесь число, значення половини літери в байтах.
Тому довелося робити ось так:

std::string last_utf8_char(const std::string& s)
{
    if (s.empty())
        return "";
    size_t pos = s.size() - 1;
    // Skip continuation bytes (0x80 to 0xBF)
    auto mask_for_bit_continuation { 0xC0 }; // check if byte is a beginning
    auto not_begin_of_symbol { 0x80 }; // not a beginning of a symbol
    while (pos > 0
           && (static_cast<unsigned char>(s[pos]) & mask_for_bit_continuation)
               == not_begin_of_symbol) {
        pos--;
    }
    return s.substr(pos);
}

Хтось знає кращий спосіб зробити це? Хто які типи даних для рядків з нелатинською абеткою використовує(wstring, u8string)?

2

Re: Дуже сумна балада про string і українську абетку

#include <iostream>
#include <string>

void print(std::wstring const &s) {
    std::wcout << s << " : "
        << s[s.length() - 1] << "\r\n";
}
int main() {
    print(L"алфавіт");
    print(L"абетка");
}
gcc 16 & clang 22 написав:
alfavit : t
abetka : a

Latynkoju tse tezh ukrajinska.