2017-02-13 11 views
1

私はCコードを作成しており、特定の文字数の後に文字列を終了する方法を見つけるのに苦労しています。たとえば、文字列dataを3文字後に終了する必要があります。それはプレーンなASCII文字列なら、私は(おそらく)マルチバイト文字列を終了しますか?

data[3] = 0; 

しかし、私の場合のような何かを行うことができます任意の文字のは、EまたはAのようなマルチバイトである可能性があります。与えられた数の文字の後でこのような文字列を終了する最も良い方法は何ですか

UPDATE:基本的に

char s_mon[7]; 

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

現在のロケールがフランス語です。月は「févr」として保存されています。 "fév"にする必要がありますが、これは普遍的である必要がありますので、 "火星"のようなエントリも3文字にカットできます。

+3

エンコーディングによってdata' –

+2

'の宣言は何が(あなたが使用しているエンコーディングを知っている必要があります)、マルチバイトシーケンスを使用するための正確なルールがあります。これらのルールを考慮して、文字列を左から右に分析します。次に、ゼロを置くことができます(UTF-8の場合は、1つの0は大丈夫です)。 – linuxfan

+2

'、'は必要ありません。 'マルチバイト'が必要です。 [8859-1](https://en.wikipedia.org/wiki/ISO/IEC_8859-1)は、単にコード200と192です。使用している文字セットは何ですか?どのようにコードが最初にテキストを読みましたか? – chux

答えて

0

これを再利用すると、utf_str_to_upper機能が終了しました。この関数は、マルチバイト値を正しく扱います。また、文字列を大文字に変換しますが、必要に応じてその機能を削除することもできます。

唯一の修正は、文字の制限である2番目のパラメータlimitを渡すことです。文字列をカットする必要があります。この関数はターミネータを正しいバイト位置に挿入し、バイト位置を返します。ここでは完全なコードです:

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

Unicodeでは、éを事前結合文字またはベース文字+分音記号として表すことができるので、最初に入力を適切な形式に正規化する必要があります。例:éを事前構成済みとして取得するNFCキャラクター。 – ninjalj

+0

@ninjalj実際にはこの場合(Pebble Dev)正しく表示するには、構成された文字をマルチバイトにする必要があります。私がピギーバックしたその機能は、このhttps://github.com/jrmobley/pebble-utf8を扱うパッケージの一部です –

関連する問題