3
votes

Copiez un std :: u8string dans une chaîne de style C de caractères utf8

Copier une chaîne sans encodage dans une chaîne C est assez simple:

auto to_c_str(std::u8string const& str) -> char8_t* {
    auto dest = new char8_t[str.size() + 1];
    return std::strcpy(dest, str.c_str());
}

Mais comment puis-je faire cela avec une std :: u8string ? Y a-t-il un algorithme STL qui peut vous aider?

J'ai essayé ceci:

auto to_c_str(std::string const& str) -> char* {
    auto dest = new char[str.size() + 1];
    return strcpy(dest, str.c_str());
}

Mais bien sûr, std :: strcpy code> n'est pas surchargé pour les chaînes utf8.


1 commentaires

La façon dont UTF-8 est défini, je ne vois aucun problème avec ce que vous avez. Vous pouvez aussi simplement utiliser memcpy pour les performances. Ou est-ce que je rate le point?


3 Réponses :


10
votes

strcpy n'est pas nécessaire puisque vous connaissez déjà la longueur de ce que vous souhaitez copier, utilisez donc memcpy :

char8_t* to_c_str(std::u8string const& str) {
    auto dest = new char8_t[str.size() + 1];
    std::copy(str.data(), str.data() + str.size() + 1, dest);
    return dest;
}

ou std::copy:

char8_t* to_c_str(std::u8string const& str) {
    auto dest = new char8_t[str.size() + 1];
    return static_cast<char8_t*>(std::memcpy(dest, str.data(), str.size()+1));
}

Depuis la u8string propre copy () ne peut pas être utilisée pour inclure directement le terminateur nul, je ne l'utiliserais pas lors de la copie dans un char8_t* brut .


1 commentaires

Je n'ai jamais eu à gérer beaucoup de cordes de style C. Cela clarifie les choses, merci.



3
votes

En plus d'utiliser std :: memcpy , vous pouvez utiliser std :: u8string :: copy et std :: copy . < pré> XXX


6 commentaires

Ou std :: char_traits :: copy juste pour ennuyer;)


@DeiDei Je présume que std :: u8string :: copy utilisera quels traits de caractère implémentent?


@DeiDei, qui savait qu'il y avait tellement de façons de copier une séquence de caractères!


@GuillaumeRacicot Très probablement, et à la fin vous vous retrouverez avec un memcpy quelque part.


Le terminateur nul serait-il u8 '\ 0' ?


@GuillaumeRacicot, j'aime cette suggestion. Merci.



1
votes

Il me semble qu'il serait plus facile d'utiliser simplement la copie intégrée et de fournir .data () au code C:

std::u8string orig = u8"abc";
auto copy = orig;
c_api(copy.data(), copy.size());

Par ce faisant, vous laissez la chaîne copiée gérer sa propre durée de vie et avoir la taille sur un pied d'égalité avec les données. Cela fonctionne uniformément pour tout type de caractère de std :: basic_string . En prime, il fonctionne également pour std::vector.


0 commentaires