首页 > 解决方案 > 使用特定编码转换字符串以获得一个字符

问题描述

我正在这个令人沮丧的旅程中试图从 Swift 字符串中获取特定字符。我有一个 Objective-C 函数,比如

- ( NSString * ) doIt: ( char ) c

我想从斯威夫特打电话。

c最终被传递给后面的一个 C 函数,该函数在这里进行举重,但是这个函数在cis 或时被绊倒了A0

现在我有两个问题(抱歉)。

  1. 我正在尝试使用不同的编码,尤其是ASCII变体,希望将 ( A0) 转换为 spcae (20或 dec 32)。结论似乎是我需要对此进行硬编码,但如果有一种故障安全、非硬编码的方式,我想听听!

  2. 我真的在为转换本身而苦苦挣扎。如何在 Swift 中使用特定编码访问特定字符?

a) 我可以使用

s.utf8CString[ i ]

但后来我一定会UTF8

b)我可以使用类似的东西

let s = "\u{a0}"
let p = UnsafeMutablePointer < CChar >.allocate ( capacity : n )

defer
{
    p.deallocate()
}

// Convert to ASCII
NSString ( string : s ).getCString ( p,
        maxLength : n,
        encoding  : CFStringConvertEncodingToNSStringEncoding ( CFStringBuiltInEncodings.ASCII.rawValue ) )

// Hope for 32
let c = p[ i ]

但这似乎有点矫枉过正。字符串被转换为NSString应用编码,我需要分配一个指针,只是为了得到一个字符。

c) 在这里,Swift String 似乎withCString是这项工作的人选,但我什至无法编译它。以下是 Xcode 的完成给出的内容,但即使在摆弄了很长时间之后,我仍然被卡住了。

// How do I use this
// ??
s.withCString ( encodedAs : _UnicodeEncoding.Protocol ) { ( UnsafePointer < FixedWidthInteger & UnsignedInteger > ) -> Result in
// ??
}

TIA

标签: objective-cswift

解决方案


有两种withCString()方法:withCString(_:)使用指向字符串内容的指针调用给定的闭包,表示为以空字符结尾的 UTF-8 代码单元序列。例子:

// An emulation of your Objective-C method.
func doit(_ c: CChar) {
    print(c, terminator: " ")
}

let s = "a\u{A0}b"
s.withCString { ptr in
    var p = ptr
    while p.pointee != 0 {
        doit(p.pointee)
        p += 1
    }
}
print()

// Output: 97 -62 -96 98

-62 -96是无间隔字符 U+00A0的 UTF-8 序列的有符号字符表示。C2 A0

如果您只想按顺序遍历字符串的所有 UTF-8 字符,那么您可以简单地使用.utf8视图。(无符号)UInt8字节必须转换为相应的(有符号)CChar

let s = "a\u{A0}b"
for c in s.utf8 {
        doit(CChar(bitPattern: c))
}
print()

我不知道将 U+00A0 转换为“普通”空格字符的方法,因此您必须手动执行此操作。和

let s = "a\u{A0}b".replacingOccurrences(of: "\u{A0}", with: " ")

上述程序的输出将是97 32 98.

withCString(encodedAs:_:)方法使用指向字符串内容的指针调用给定的闭包,表示为以空字符结尾的代码单元序列。例子:

let s = "a\u{A0}b€&quot;
s.withCString(encodedAs: UTF16.self) { ptr in
    var p = ptr
    while p.pointee != 0 {
        print(p.pointee, terminator: " ")
        p += 1
    }
}
print()

// Output: 97 160 98 8364

此方法可能对您的目的用途有限,因为它只能与UTF8,UTF16和一起使用UTF32

对于其他编码,您可以使用该data(using:)方法。它产生一个Data值,该值是UInt8(无符号类型)的序列。如上所述,这些必须转换为相应的有符号字符:

let s = "a\u{A0}b"
if let data = s.data(using: .isoLatin1) {
    data.forEach {
        doit(CChar(bitPattern: $0))
    }
}
print()

// Output: 97 -96 98

当然,如果字符串在给定的编码中不可表示,这可能会失败。


推荐阅读