How to get the actual length of a UTF-8 encoded std::string in C++

1 Answer

0 votes
#include <iostream>
#include <string>

/*
    Function: utf8_length
    ---------------------
    Counts how many Unicode code points exist in a UTF‑8 encoded std::string.

    Why this is needed:
    -------------------
    - std::string::size() returns the number of BYTES.
    - UTF‑8 characters may use 1–4 bytes.
    - To count actual characters (code points), we must decode UTF‑8 manually.

    UTF‑8 encoding rules:
    ---------------------
    1-byte: 0xxxxxxx
    2-byte: 110xxxxx 10xxxxxx
    3-byte: 1110xxxx 10xxxxxx 10xxxxxx
    4-byte: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
*/
size_t utf8_length(const std::string& s) {
    size_t length = 0;   // number of Unicode code points
    size_t i = 0;        // index into the byte string

    while (i < s.size()) {
        unsigned char c = s[i];

        // Determine how many bytes this UTF‑8 character uses
        if (c < 0x80) {
            // 1-byte ASCII character
            i += 1;
        }
        else if ((c >> 5) == 0x6) {
            // 110xxxxx → 2-byte character
            i += 2;
        }
        else if ((c >> 4) == 0xE) {
            // 1110xxxx → 3-byte character
            i += 3;
        }
        else if ((c >> 3) == 0x1E) {
            // 11110xxx → 4-byte character
            i += 4;
        }
        else {
            // Invalid UTF‑8 byte encountered
            throw std::runtime_error("Invalid UTF‑8 encoding detected.");
        }

        length++;  // Count one Unicode code point
    }

    return length;
}

int main() {
    // Example UTF‑8 string containing Japanese characters
    std::string text = u8"世界、こんにちは";  // "Hello world" in Japanese // kon-ni-chi-wa

    // Print raw byte length
    std::cout << "Byte length (std::string::size): " << text.size() << "\n";

    // Print actual Unicode code point length
    std::cout << "UTF‑8 code point length: " << utf8_length(text) << "\n";
}


/*
run:

Byte length (std::string::size): 24
UTF‑8 code point length: 8

*/

 



answered Jul 1 by avibootz

Related questions

...