十六进制字符串到 PURE Swift 中的字符

Hex String to Character in PURE Swift

我需要一种方法将包含表示十六进制值的文字字符串的字符串转换为对应于该特定十六进制值的字符。

理想情况下,遵循以下原则:

let hexString: String = "2C"
let char: Character = fromHexString(hexString)
println(char)   // prints -> ","

我尝试使用语法:“\u{n}”,其中 n 是 Int 或 String,但均无效。

这可用于循环遍历 hexString 数组,如下所示:

var hexArray = ["2F", "24", "40", "2A"]
var charArray = [Character]()
charArray = map(hexArray) { charArray.append(Character([=12=])) }
charArray.description // prints -> "[/, $, @, *]"

关于您的代码的几件事:

var charArray = [Character]()
charArray = map(hexArray) { charArray.append(Character([=10=])) }

不需要创建数组再赋值map的结果,直接赋值即可,避免创建不必要的数组。

charArray = map(hexArray) { charArray.append(Character([=11=])) }

在这里您可以使用 hexArray.map 而不是 map(hexArray),当您使用映射函数时,您在概念上所做的是将接收方数组的元素映射到一组新的值和映射的结果是新的 "mapped" 数组,这意味着您不需要在映射闭包中执行 charArray.append

无论如何,这是一个工作示例:

let hexArray = ["2F", "24", "40", "2A"]
var charArray = hexArray.map { char -> Character in
    let code = Int(strtoul(char, nil, 16))
    return Character(UnicodeScalar(code))
}
println(charArray) // -> [/, $, @, *]

编辑:这是另一个不需要基础的实现:

func hexToScalar(char: String) -> UnicodeScalar {
    var total = 0
    for scalar in char.uppercaseString.unicodeScalars {
        if !(scalar >= "A" && scalar <= "F" || scalar >= "0" && scalar <= "9") {
            assertionFailure("Input is wrong")
        }

        if scalar >= "A" {
            total = 16 * total + 10 + scalar.value - 65 /* 'A' */
        } else {
            total = 16 * total + scalar.value - 48 /* '0' */
        }
    }
    return UnicodeScalar(total)
}

let hexArray = ["2F", "24", "40", "2A"]
var charArray = hexArray.map { Character(hexToScalar([=13=])) }
println(charArray)

EDIT2 还有一个选项:

func hexToScalar(char: String) -> UnicodeScalar {
    let map = [ "0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9,
        "A": 10, "B": 11, "C": 12, "D": 13, "E": 14, "F": 15 ]

    let total = reduce(char.uppercaseString.unicodeScalars, 0, { [=14=] * 16 + (map[String()] ?? 0xff) })
    if total > 0xFF {
        assertionFailure("Input char was wrong")
    }
    return UnicodeScalar(total)
}

最终编辑:解释

鉴于 ascii table 包含所有数字 (012345679),我们可以将 'N'(基数 10)转换为知道 ascii 值为 0 的整数。

因为:

'0': 48
'1': 49
...
'9': 57

然后,例如,如果您需要将“9”转换为 9,您可以这样做

asciiValue('9') - asciiValue('0') => 57 - 48 = 9

你也可以从 'A' 到 'F':

'A': 65
'B': 66
...
'F': 70

现在我们可以像以前一样做,但是,例如 'F' 我们会做:

asciiValue('F') - asciiValue('A') => 70 - 65 = 5

请注意,我们需要将此数字加 10 以获得小数。然后(回到代码):如果标量在 A-Z 之间,我们需要做:

10 + asciiValue(<letter>) - asciiValue('A')

与以下内容相同:10 + scalar.value - 65

如果它在 0-9 之间:

asciiValue(<letter>) - asciiValue('0')

与以下内容相同:scalar.value - 48

例如:'2F'

'2' 是 2 而 'F' 是 15(通过前面的例子),对吧?。由于十六进制是以 16 为底,我们需要做的是:

((16 ^ 1) * 2) + ((16 ^ 0) * 15) = 47

给你:

var string = String(UnicodeScalar(Int("2C", radix: 16)!))

顺便说一句,您可以像这样在文字字符串中包含十六进制值:

var string = "\u{2c}"

使用 Swift 5,您必须将字符串变量转换为整数(使用 init(_:radix:) initializer), create Unicode scalar from this integer (using init(_:)) then create a character from this Unicode scalar (using init(_:))。

下面的 Swift 5 Playground 示例代码显示了如何进行:

let validHexString: String = "2C"
let validUnicodeScalarValue = Int(validHexString, radix: 16)!
let validUnicodeScalar = Unicode.Scalar(validUnicodeScalarValue)!
let character = Character(validUnicodeScalar)
print(character) // prints: ","

如果要对数组中的元素执行此操作,可以使用下面的示例代码:

let hexArray = ["2F", "24", "40", "2A"]
let characterArray = hexArray.map({ (hexString) -> Character in
    let unicodeScalarValue = Int(hexString, radix: 16)!
    let validUnicodeScalar = Unicode.Scalar(unicodeScalarValue)!
    return Character(validUnicodeScalar)
})
print(characterArray) // prints: ["/", "$", "@", "*"]

没有强制展开的替代方案:

let hexArray = ["2F", "24", "40", "2A"]
let characterArray = hexArray.compactMap({ (hexString) -> Character? in
    guard let unicodeScalarValue = Int(hexString, radix: 16),
        let unicodeScalar = Unicode.Scalar(unicodeScalarValue) else {
            return nil
    }
    return Character(unicodeScalar)
})
print(characterArray) // prints: ["/", "$", "@", "*"]

另一种基于 ICU 转换的简单方法:

extension String {
  func transformingFromHex() -> String? {
    return "&#x\(self);".applyingTransform(.toXMLHex, reverse: true)
  }
}

用法:

"2C".transformingFromHex()

结果:,