Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C++

Hàm mbrtowc() trong C/C++ - Chuyển đổi đa byte sang ký tự rộng

Hàm mbrtowc() (Multibyte to Wide Character) chuyển đổi một chuỗi đa byte (multibyte string, thường là UTF-8) thành ký tự rộng (wchar_t). Đây là hàm an toàn, hỗ trợ trạng thái chuyển đổi (state-dependent encoding).

Chữ ký hàm

size_t mbrtowc(wchar_t *restrict wc, const char *restrict s, size_t n, mbstate_t *restrict ps);

Tham số

Tham sốÝ nghĩa
wcCon trỏ lưu ký tự rộng kết quả (có thể NULL để chỉ đếm byte).
sCon trỏ đến chuỗi đa byte đầu vào.
nSố byte tối đa kiểm tra từ s.
psCon trỏ trạng thái chuyển đổi (mbstate_t), dùng cho encoding có trạng thái. Truyền NULL để dùng trạng thái nội bộ tĩnh.

Giá trị trả về

  • 0: Ký tự null (chuỗi kết thúc).
  • 1..n: Số byte đã tiêu thụ để tạo ký tự rộng.
  • (size_t)(-1): Lỗi encoding (dãy byte không hợp lệ), đặt errno = EILSEQ.
  • (size_t)(-2): Chuỗi không đầy đủ (cần thêm byte), chuyển đổi chưa hoàn tất.

Ví dụ: Phân tích chuỗi UTF-8

#include <bits/stdc++.h> // GCC/Clang: bao gồm tất cả header chuẩn
#include <wchar.h>
#include <locale.h>

using namespace std;

void display(const char* s) {
    mbstate_t ps = {};        // Trạng thái ban đầu (zero-initialized)
    size_t len = strlen(s);
    const char* end = s + len;
    wchar_t wc;
    size_t rc;

    while ((rc = mbrtowc(&wc, s, end - s, &ps)) > 0) {
        wcout << L"Ky tu: " << wc << L", so byte: " << rc << L'\n';
        s += rc; // Tiến con trỏ
    }
    
    if (rc == (size_t)(-1)) wcout << L"Loi encoding!\n";
    else if (rc == (size_t)(-2)) wcout << L"Chuoi khong day du!\n";
}

int main() {
    // Thiết lập locale hỗ trợ UTF-8
    setlocale(LC_ALL, "en_US.utf8");
    
    // Chuỗi UTF-8: 'z' (1 byte), 'Ï' (2 byte), '簸' (3 byte), 'क' (3 byte)
    const char* str = u8"z\u00cf\u7c38\U00000915";
    
    display(str);
    return 0;
}

Kết quả

Ky tu: z, so byte: 1
Ky tu: Ï, so byte: 2
Ky tu: 簸, so byte: 3
Ky tu: क, so byte: 3

Lưu ý quan trọng

  • Luôn gọi setlocale(LC_ALL, "") hoặc locale cụ thể (UTF-8) trước khi dùng hàm wide-char.
  • mbstate_t ps = {}; khởi tạo trạng thái zero (an toàn).
  • Dùng wcout để in wchar_t; cần <iostream> và locale.
  • Để chuyển ngược (wide → multibyte), dùng wcrtomb().
  • C++11 cung cấp std::wstring_convert và std::codecvt (deprecated C++17), hiện nay khuyên dùng ICU hoặc std::from_chars/to_chars (chỉ số nguyên).

mbrtowc là công cụ cơ bản để xử lý Unicode trong C/C++ chuẩn, đặc biệt khi không thể dùng thư viện bên thứ ba.