歡迎加入QQ討論群258996829
贏了現(xiàn)在輸了未來 頭像
蘋果2袋
2
贏了現(xiàn)在輸了未來

Swift 中 String 與 CChar 數(shù)組的轉(zhuǎn)換

發(fā)布時(shí)間:2015-10-17 15:03  回復(fù):0  查看:4217   最后回復(fù):2015-10-17 15:03  

在現(xiàn)階段Swift的編碼中,我們還是有很多場景需要調(diào)用一些C函數(shù)。在Swift與C的混編中,經(jīng)常遇到的一個(gè)問題就是需要在兩者中互相轉(zhuǎn)換字符串。在C語言中,字符串通常是用一個(gè)char數(shù)組來表示,在Swift中,是用CChar數(shù)組來表示。從CChar的定義可以看到,其實(shí)際上是一個(gè)Int8類型,如下所示:

/// The C 'char' type.
///
/// This will be the same as either `CSignedChar` (in the common
/// case) or `CUnsignedChar`, depending on the platform.
public typealias CChar = Int8
如果我們想將一個(gè)String轉(zhuǎn)換成一個(gè)CChar數(shù)組,則可以使用String的cStringUsingEncoding方法,它是String擴(kuò)展中的一個(gè)方法,其聲明如下:

/// Returns a representation of the `String` as a C string
/// using a given encoding.
@warn_unused_result
public func cStringUsingEncoding(encoding: NSStringEncoding) -> [CChar]?
參數(shù)指定的是編碼格式,我們一般指定為NSUTF8StringEncoding,因此下面這段代碼:

let str: String = "abc1個(gè)"
// String轉(zhuǎn)換為CChar數(shù)組
let charArray: [CChar] = str.cStringUsingEncoding(NSUTF8StringEncoding)!
其輸出結(jié)果是:

[97, 98, 99, 49, -28, -72, -86, 0]

可以看到"個(gè)"字由三個(gè)字節(jié)表示,這是因?yàn)镾wift的字符串是Unicode編碼格式,一個(gè)字符可能由1個(gè)或多個(gè)字節(jié)組成。另外需要注意的是CChar數(shù)組的最后一個(gè)元素是0,它表示的是一個(gè)字符串結(jié)束標(biāo)志符\n。

我們知道,在C語言中,一個(gè)數(shù)組還可以使用指針來表示,所以字符串也可以用char *來表示。在Swift中,指針是使用UnsafePointer或UnsafeMutablePointer來包裝的,因此,char指針可以表示為UnsafePointer,不過它與[CChar]是兩個(gè)不同的類型,所以以下代碼會報(bào)編譯器錯(cuò)誤:

// Error: Cannot convert value of type '[CChar]' to specified type 'UnsafePointer'
let charArray2: UnsafePointer = str.cStringUsingEncoding(NSUTF8StringEncoding)!
不過有意思的是我們可以直接將String字符串傳遞給帶有UnsafePointer參數(shù)的函數(shù)或方法,如以下代碼所示:

func length(s: UnsafePointer) {
    print(strlen(s))
}
length(str)
// 輸出:7\n
而String字符串卻不能傳遞給帶有[CChar]參數(shù)的函數(shù)或方法,如以下代碼會報(bào)錯(cuò)誤:

func length2(s: [CChar]) {
    print(strlen(s))
}
// Error: Cannot convert value of type 'String' to expected argument type '[CChar]'
length2(str)
實(shí)際上,在C語言中,我們在使用數(shù)組參數(shù)時(shí),很少以數(shù)組的形式來定義參數(shù),則大多是通過指針方式來定義數(shù)組參數(shù)。

如果想從[CChar]數(shù)組中獲取一上String字符串,則可以使用String的fromCString方法,其聲明如下:

/// Creates a new `String` by copying the nul-terminated UTF-8 data
/// referenced by a `CString`.
///
/// Returns `nil` if the `CString` is `NULL` or if it contains ill-formed
/// UTF-8 code unit sequences.
@warn_unused_result
public static func fromCString(cs: UnsafePointer) -> String?
從注釋可以看到,它會將UTF-8數(shù)據(jù)拷貝以新字符串中。如下示例:

let chars: [CChar] = [99, 100, 101, 0]
let str2: String = String.fromCString(chars)!
// 輸出:cde
這里需要注意的一個(gè)問題是,CChar數(shù)組必須以0結(jié)束,否則會有不可預(yù)料的結(jié)果。在我的Playground示例代碼中,如果沒有0,報(bào)了以下錯(cuò)誤:

Execution was interrupted. reason: EXC_BAD_INSTRUCTION

小結(jié)

在Swift中,String是由獨(dú)立編碼的Unicode字符組成的,即Character。一個(gè)Character可能包括一個(gè)或多個(gè)字節(jié)。所以將String字符串轉(zhuǎn)換成C語言的char *時(shí),數(shù)組元素的個(gè)數(shù)與String字符的個(gè)數(shù)不一定相同(即在Swift中,與str.characters.count計(jì)算出來的值不一定相等)。這一點(diǎn)需要注意。另外還需要注意的就是將CChar數(shù)組轉(zhuǎn)換為String時(shí),數(shù)組最后一個(gè)元素應(yīng)當(dāng)為字符串結(jié)束標(biāo)志符,即0。

參考

  1. UTF8String

  2. String Structure Reference

  3. The Swift Programming Language中文版


您還未登錄,請先登錄

熱門帖子

最新帖子

?