2017-02-13 3 views
1

Je travaille sur un code C et j'ai du mal à trouver un moyen de terminer une chaîne après un certain nombre de caractères. Par exemple, je dois terminer la chaîne data après 3 caractères. Si c'est une chaîne ASCII, je peux faire quelque chose commeTermine (éventuellement) une chaîne multi-octets?

data[3] = 0; 

Mais dans mon cas, l'un des personnages pourrait être multi-octets comme E ou A. Quel serait le meilleur moyen de terminer une telle chaîne après un nombre donné de caractères?

MISE À JOUR:

En gros:

char s_mon[7]; 

setlocale(LC_ALL, ""); 
strftime(s_mon, 7, "%b", tick_time); 

locale actuelle est le français. Le mois est stocké comme "févr". Besoin d'être "fév", mais cela doit être universel, donc des entrées comme "mars" pourraient aussi être coupées en 3 caractères.

+3

Quelle est la déclaration de 'data' –

+2

Selon l'encodage (vous devez savoir ce que vous utilisez encodage), il existe des règles précises pour l'utilisation de séquences multi-octets. Vous analysez la chaîne de gauche à droite, en tenant compte de ces règles, jusqu'à ce que vous dépassiez le Nième caractère. Ensuite, vous pouvez mettre un zéro (pour UTF-8, un seul 0 est ok par exemple). – linuxfan

+2

'È',' À' ne demandent pas de "multi-octets". Avec [8859-1] (https://en.wikipedia.org/wiki/ISO/IEC_8859-1) ils sont simplement les codes 200 et 192. Quel est le jeu de caractères que vous utilisez? Comment le code at-il lu le texte en premier lieu? – chux

Répondre

0

Terminé en réutilisant cette fonction utf_str_to_upper. La fonction traite correctement les valeurs multi-octets. Il convertit également la chaîne en majuscules (dont j'avais également besoin) mais cette fonctionnalité peut être supprimée si nécessaire.

La seule modification que j'ai faite est de passer le deuxième paramètre limit qui est limite en caractères à laquelle j'ai besoin de couper la chaîne. La fonction insère alors le terminateur à la position correcte de l'octet et renvoie la position de l'octet. Voici le code complet:

uint8_t utf8_str_to_upper(char* s, uint8_t limit) { 

    uint8_t char_no = 0; 
    uint8_t* p; 

    for (p = (uint8_t*)s; *p; ++p) { 

     // (<128) ascii character 
     // U+00000000 – U+0000007F: 0xxxxxxx 
     if (*p < 0b10000000) { 
      if (*p >= 0x61 && *p <= 0x7A) { 
       *p = *p - 0x20; // a~z -> A~Z 
      } 

     // (<192) unexpected continuation byte 
     } else if (*p < 0b11000000) { 

     // (<224) 2 byte sequence 
     // U+00000080 – U+000007FF: 110xxxxx 10xxxxxx 
     } else if (*p < 0b11100000) { 
      uint16_t code = ((uint16_t)(p[0] & 0b00011111) << 6) | (p[1] & 0b00111111); 
      if (
       (code >= 0x00E0 && code <= 0x00F6) || // à~ö -> À~Ö 
       (code >= 0x00F8 && code <= 0x00FE) // ø~þ -> Ø~Þ 
      ) { 
       code -= 0x0020; 
       p[0] = 0b11000000 | ((code >> 6) & 0b00011111); 
       p[1] = 0b10000000 | (code  & 0b00111111); 
      } 
      ++p; 

     // (<240) 3 byte sequence 
     // U+00000800 – U+0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx 
     } else if (*p < 0b11110000) { 
      p += 2; 

     // (<248) 4 byte sequence 
     // U+00010000 – U+001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 
     } else if (*p < 0b11111000) { 
      p += 3; 

     // (<252) 5 byte sequence 
     // U+00200000 – U+03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 
     } else if (*p < 0b11111100) { 
      p += 4; 

     // (<254) 6 byte sequence 
     // U+04000000 – U+7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 
     } else if (*p < 0b11111110) { 
      p += 5; 
     } 

     if (limit) { 
      char_no++; 

      if (char_no == limit) { 
       *(p + 1) = 0; 
       return p-(uint8_t*)s + 1; 
       break; 
      } 

     } 

    } 

    return p-(uint8_t*)s + 1; 
} 
+0

Veuillez noter que dans Unicode, é peut être représenté soit comme un caractère précomposé, soit comme un caractère de base + diacritique, donc vous devrez d'abord normaliser l'entrée à une forme appropriée, par exemple: à NFC pour obtenir é comme précomposé personnage. – ninjalj

+0

@ ninjalj en fait dans ce cas (Pebble Dev) Je dois décider des caractères composés en multi-octets pour être correctement affichés. Cette fonction que j'ai piggy-soutenu est une partie du paquet qui traite de ce https://github.com/jrmobley/pebble-utf8 –