Swift 中 String 与 CChar 数组的转换

在现阶段Swift的编码中,我们还是有很多场景需要调用一些C函数。在Swift与C的混编中,经常遇到的一个问题就是需要在两者中互相转换字符串。在C语言中,字符串通常是用一个char数组来表示,在Swift中,是用CChar数组来表示。从CChar的定义可以看到,其实际上是一个Int8类型,如下所示:


1

2

3

4

5

/// 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

如果我们想将一个String转换成一个CChar数组,则可以使用String的cStringUsingEncoding方法,它是String扩展中的一个方法,其声明如下:


1

2

3

4

/// Returns a representation of the `String` as a C string

/// using a given encoding.

@warn_unused_result

public func cStringUsingEncoding(encoding: NSStringEncoding) -> [CChar]?

参数指定的是编码格式,我们一般指定为NSUTF8StringEncoding,因此下面这段代码:


1

2

3

let str: String = "abc1个"

// String转换为CChar数组

let charArray: [CChar] = str.cStringUsingEncoding(NSUTF8StringEncoding)!

其输出结果是:


1

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

可以看到"个"字由三个字节表示,这是因为Swift的字符串是Unicode编码格式,一个字符可能由1个或多个字节组成。另外需要注意的是CChar数组的最后一个元素是0,它表示的是一个字符串结束标志符\n。

我们知道,在C语言中,一个数组还可以使用指针来表示,所以字符串也可以用char *来表示。在Swift中,指针是使用UnsafePointer或UnsafeMutablePointer来包装的,因此,char指针可以表示为UnsafePointer,不过它与[CChar]是两个不同的类型,所以以下代码会报编译器错误:


1

2

// Error: Cannot convert value of type ‘[CChar]‘ to specified type ‘UnsafePointer‘

let charArray2: UnsafePointer = str.cStringUsingEncoding(NSUTF8StringEncoding)!

不过有意思的是我们可以直接将String字符串传递给带有UnsafePointer参数的函数或方法,如以下代码所示:


1

2

3

4

5

func length(s: UnsafePointer) {

    print(strlen(s))

}

length(str)

// 输出:7\n

而String字符串却不能传递给带有[CChar]参数的函数或方法,如以下代码会报错误:


1

2

3

4

5

func length2(s: [CChar]) {

    print(strlen(s))

}

// Error: Cannot convert value of type ‘String‘ to expected argument type ‘[CChar]‘

length2(str)

实际上,在C语言中,我们在使用数组参数时,很少以数组的形式来定义参数,则大多是通过指针方式来定义数组参数。

如果想从[CChar]数组中获取一上String字符串,则可以使用String的fromCString方法,其声明如下:


1

2

3

4

5

6

7

/// 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数据拷贝以新字符串中。如下示例:


1

2

3

let chars: [CChar] = [99, 100, 101, 0]

let str2: String = String.fromCString(chars)!

// 输出:cde

这里需要注意的一个问题是,CChar数组必须以0结束,否则会有不可预料的结果。在我的Playground示例代码中,如果没有0,报了以下错误:


1

Execution was interrupted. reason: EXC_BAD_INSTRUCTION

还有可能出现的情况是CChar数组的存储区域正好覆盖了之前某一对象的区域,这一对象有一个可以表示字符串结尾的标识位,则这时候,str2输出的可能是"cde1一"。

小结

在Swift中,String是由独立编码的Unicode字符组成的,即Character。一个Character可能包括一个或多个字节。所以将String字符串转换成C语言的char *时,数组元素的个数与String字符的个数不一定相同(即在Swift中,与str.characters.count计算出来的值不一定相等)。这一点需要注意。另外还需要注意的就是将CChar数组转换为String时,数组最后一个元素应当为字符串结束标志符,即0。

时间: 2024-10-10 04:57:26

Swift 中 String 与 CChar 数组的转换的相关文章

关于C中字符数组,字符指针以及C++中string类型的两两转换及排序

// practise.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <string.h> #include <string> #include <algorithm> #include <iostream> using namespace std; int main() { /* 字符串转字符数组,使用strncpy_s(),比strncpy()安全*/ string str

swift 中String常用操作

1.  字符串定义 var s = "aaaaaa" // 两个字符串均为空并等价. var emptyString = ""   var anotherEmptyString = String() 字符串字面量可以包含以下特殊字符:转义字符  \0 (空字符).  \\ (反斜线).  \t (水平制表符).  \n (换行符). \r (回车符).  \" (双引号).  \' (单引号). 单字节 Unicode 标量,写成  \xnn ,其中  n

Swift中的元组,数组,字典

元组(Tuples)与数组和字典的差别较大,元组是把多个值组成一个复合值: let http 404 Error = (404,"Not Found") //http 404 的类型是(Int,String),值是(404,"Not Found") 可以在定义元组的时候给单个元素命名,这时候元组的数组有一些相似: let http200Status = (statusCode: 200, description: "OK") 数组(Array)和

swift 中String,Int 等类型使用注意,整理中

swfit中的String和Int是 struct定义的,不同于NSString和NSNumber, 如果想在一个数组中同时包含String和Int,那么这个数组要声明为[Any] 而不是 [AnyObject] , 因为他们不是class! 另外,与c中的string和int 不同,swfit中的是struct,虽然在使用上,可以把Int当做int使用,它代表了基本的整型,可以达到c中的int的功能,但是数据结构上是不同的,具体来说,

C# String与Byte数组的转换

string转byte[]: byte[] byteArray = System.Text.Encoding.Default.GetBytes(str); byte[] byteArray = Encoding.Default.GetBytes(str); byte[]转string: string str = System.Text.Encoding.Default.GetString(byteArray); string str = Encoding.Default.GetString(by

LeetCode中String to Integer (atoi) 字符串转换成整数

int atoi(const char *str) { long long result = 0; while (*str==' ')str++; int flag=0; if (*str == '-' || *str == '+') { flag = (*str == '-') ? -1 : 1; str++; } while (*str!='\0') { int temp = *str - '0'; if (temp >= 0 && temp <= 9) { result

Swift - 将String类型的数字转换成数字类型(支持十进制、十六进制)

1,十进制的字符串转成数字 Swift中,如果要把字符串转换成数字类型(比如整型,浮点型等).可以先转成NSString类型,让后再转. 1 2 3 4 //将文本框中的值转换成数字 var i = (tf1.text as NSString).intValue var f = (tf1.text as NSString).floatValue var d = (tf1.text as NSString).doubleValue 2,十六进制的字符串转成数字 (1)定义一个转换方法 1 2 3

Swift - 将String类型的数字转换成数字类型

Swift中,如果要把字符串转换成数字类型(比如整型,浮点型等).可以先转成NSString类型,让后再转. 1 2 3 4 //将文本框中的值转换成数字 var i = (tf1.text as NSString).intValue var f = (tf1.text as NSString).floatValue var d = (tf1.text as NSString).doubleValue

Swift Explore - 关于 Swift 中的 isEqual 的一点探索

在我们进行 App 开发的时候,经常会用到的一个操作就是判断两个对象是否相等.比如两个字符串是否相等.而所谓的 相等 有着两层含义.一个是值相等,还有一个是引用相等.如果熟悉 Objective-C 开发的话,就会知道 Objective-C 为我们提供了一系列 isEqual: 方法来判断值相等,而 == 等于号用来判断引用相等. 我们来看一个 Objective-C 的例子就会更加明白了: NSArray *arr1 = @[@"cat",@"hat",@&qu