2017-02-13 106 views
1

我正在研究C代碼,並努力尋找一種方法來終止特定數量的字符後的字符串。例如,我需要在3個字符後終止字符串data。如果它是一個純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」,但這需要具有普遍性,所以像「mars」這樣的條目也可以縮減爲3個字符。

+3

什麼是'data' –

+2

根據編碼聲明(你應該知道你正在使用的編碼),對於使用多字節序列精確的規則。你從左到右分析字符串,考慮這些規則,直到你越過第N個字符。然後你可以放一個零(對於UTF-8,例如單個0就可以)。 – linuxfan

+2

''','''''''''''''''''''''''''''''''''''請勿需要「多字節」。使用[8859-1](https://en.wikipedia.org/wiki/ISO/IEC_8859-1),它們只是代碼200和192.你使用的字符集是什麼?代碼是如何讀取文本的? – chux

回答

0

結束重用此utf_str_to_upper函數。該函數正確處理多字節值。它也將字符串轉換爲大寫(我也需要),但如果需要,可以剝離該功能。

我做的唯一修改是傳遞第二個參數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實際上在這種情況下(卵石開發)我必須決定組成字符到多字節才能正確顯示。我揹負的這個功能是處理這個https://github.com/jrmobley/pebble-utf8的軟件包的一部分 –