2009-11-21 129 views
27

我有一個存儲在unichar變量中的國際字符。這個角色不是來自文件或網址。變量本身只存儲一個UTF-8格式的unsigned short(0xce91),並轉換爲希臘大寫字母'A'。我試圖把這個角色放到NSString變量中,但我失敗了。如何將unichar值轉換爲Objective-C中的NSString?

我已經試過兩種不同的方式這兩個不成功的:

unichar greekAlpha = 0xce91; //could have written greekAlpha = 'Α' instead. 

NSString *theString = [NSString stringWithFormat:@"Greek Alpha: %C", greekAlpha]; 

沒有好。我有一些奇怪的漢字。作爲一個旁註,這與英文字符完美配合。

然後我也試過這樣:

NSString *byteString = [[NSString alloc] initWithBytes:&greekAlpha 
               length:sizeof(unichar) 
               encoding:NSUTF8StringEncoding]; 

但是,這也不行。 我明顯在做一些非常錯誤的事情,但我不知道該怎麼做。 有人可以幫我嗎? 謝謝!

+0

您可以通過按下編輯器工具欄中的小按鈕101010來格式化代碼以獲得更好的格式。 – hallski 2009-11-21 16:07:48

+0

謝謝你讓我知道:) – Terry 2009-11-21 16:21:16

+1

你確定'unichar'是在這裏使用的正確的數據類型嗎?將UTF-8數據存儲爲用於UTF-16的類型存在錯誤。正如Jon Jardine所指出的那樣,UTF-8字符長度超過16位......你可以使用NSString作爲單個字符嗎('NSString greekAlpha = @「Α」'然後在'stringWithFormat'中使用%@)? – 2010-06-08 14:28:05

回答

21

由於0xce91採用UTF-8格式,而%C預計採用UTF-16,所以上面的簡單解決方案將無法工作。要使用stringWithFormat:@"%C"工作,您需要輸入0x391這是UTF-16 unicode。

爲了從UTF-8編碼的unichar創建一個字符串,您需要先將unicode拆分爲八位字節,然後使用initWithBytes:length:encoding

unichar utf8char = 0xce91; 
char chars[2]; 
int len = 1; 

if (utf8char > 127) { 
    chars[0] = (utf8char >> 8) & (1 << 8) - 1; 
    chars[1] = utf8char & (1 << 8) - 1; 
    len = 2; 
} else { 
    chars[0] = utf8char; 
} 

NSString *string = [[NSString alloc] initWithBytes:chars 
              length:len 
              encoding:NSUTF8StringEncoding]; 
+0

我仔細看了一下我發佈的鏈接後,我意識到了這一點。我用這些信息和解決方案更新了我的答案。 – hallski 2009-11-21 18:55:41

+4

謝謝。這正是我所期待的!那麼,我的位就是亂七八糟的:)。 儘管我是這個網站的新成員,但我已經使用了它一段時間了(主要用於c#的東西,只是讓我的腳溼透了objective-c),而且我發現有些人會走多遠去幫助別人。再一次,謝謝你! :) – Terry 2009-11-21 20:57:06

+0

@Terry - StackOverflow是程序員懶惰規則的一個反例。一個奇怪的現象是99%的Linux從未被代碼審查過,但幾乎所有關於SO的問題,回答和評論都經過了審查,編輯,投票和討論。 SO的特性與MetaStackOverflow完全相同。 – ArtOfWarfare 2014-01-03 02:46:35

2

上述答案很好,但沒有考慮超過16位的UTF-8字符,例如,省略符號 - 0xE2,0x80,0xA6。這是對代碼的調整:

if (utf8char > 65535) { 
    chars[0] = (utf8char >> 16) & 255; 
    chars[1] = (utf8char >> 8) & 255; 
    chars[2] = utf8char & 255; 
    chars[3] = 0x00; 
} else if (utf8char > 127) { 
    chars[0] = (utf8char >> 8) & 255; 
    chars[1] = utf8char & 255; 
    chars[2] = 0x00; 
} else { 
    chars[0] = utf8char; 
    chars[1] = 0x00; 
} 
NSString *string = [[[NSString alloc] initWithUTF8String:chars] autorelease]; 

請注意不需要長度參數的不同字符串初始化方法。

+3

但'unichar'是16位類型,所以'utf8char'不能保存超過16位的值。 – 2010-06-08 14:09:11

1

這裏是一個字符爲UTF-8編碼的算法:

if (utf8char<0x80){ 
    chars[0] = (utf8char>>0) & (0x7F | 0x00); 
    chars[1] = 0x00; 
    chars[2] = 0x00; 
    chars[3] = 0x00; 
} 
else if (utf8char<0x0800){ 
    chars[0] = (utf8char>>6) & (0x1F | 0xC0); 
    chars[1] = (utf8char>>0) & (0x3F | 0x80); 
    chars[2] = 0x00; 
    chars[3] = 0x00; 
} 
else if (utf8char<0x010000) { 
    chars[0] = (utf8char>>12) & (0x0F | 0xE0); 
    chars[1] = (utf8char>>6) & (0x3F | 0x80); 
    chars[2] = (utf8char>>0) & (0x3F | 0x80); 
    chars[3] = 0x00; 
} 
else if (utf8char<0x110000) { 
    chars[0] = (utf8char>>18) & (0x07 | 0xF0); 
    chars[1] = (utf8char>>12) & (0x3F | 0x80); 
    chars[2] = (utf8char>>6) & (0x3F | 0x80); 
    chars[3] = (utf8char>>0) & (0x3F | 0x80); 
} 
51
unichar greekAlpha = 0x0391; 
NSString* s = [NSString stringWithCharacters:&greekAlpha length:1]; 

現在你可以結合的NSString到另一個你喜歡的任何方式。但是,請注意,現在將希臘字母直接輸入到NSString文字中是合法的。

+0

這隻適用於一個角色。不知道爲什麼這是downvoted。 +1 – 2011-08-31 12:27:14

+0

工作就像一個魅力! – dpalmajr 2014-01-26 04:40:13

+0

爲什麼這不是答案? – stonedauwg 2017-01-19 18:14:55

1

上面的代碼是unichar foo = 'abc';的道德等價物。

的問題是,'Α'不映射到一個字節中的「執行字符集」(我假定UTF-8),它是「實現定義的」在C99§6.4.4.410:

包含多個字符(例如'ab')或包含未映射到單字節執行字符的字符或轉義序列的整數字符常量的值是實現定義的。

一種方法是使'ab'等於'a'<<8|b。一些Mac/iOS系統頭文件依賴於此,例如OSType/FourCharCode/FourCC;在iOS中唯一想到的就是CoreVideo像素格式。然而,這是不可移植的。

如果你真的想要一個unichar文字,你可以嘗試L'A'(技術上這是一個wchar_t文字,但在OS X和iOS,wchar_t通常是UTF-16,它會爲工作的事情了BMP內)。然而,只要使用@"Α"(只要您正確設置源字符編碼就行)或@"\u0391"(自至少iOS 3 SDK以來一直運行)就簡單多了。