我需要一种方法将包含表示十六进制值的文字字符串的字符串转换为对应于该特定十六进制值的字符。
理想情况下,沿着这些方向:
let hexString: String = "2C"
let char: Character = fromHexString(hexString)
println(char) // prints -> ","
我试过使用语法:“\ u {n}”其中n是Int或String,但都不起作用。
这可以用来循环遍历一个hexStrings数组,如下所示:
var hexArray = ["2F", "24", "40", "2A"]
var charArray = [Character]()
charArray = map(hexArray) { charArray.append(Character($0)) }
charArray.description // prints -> "[/, $, @, *]"
关于代码的一些事情:
var charArray = [Character]()
charArray = map(hexArray) { charArray.append(Character($0)) }
您不需要创建数组然后分配地图的结果,您可以只分配结果并避免创建不必要的数组。
charArray = map(hexArray) { charArray.append(Character($0)) }
在这里你可以使用hexArray.map
而不是map(hexArray)
,当你使用map函数时,你在概念上做的是将接收器数组的元素映射到一组新的值,映射的结果是新的“映射”数组,意味着你不需要在地图闭包内做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($0)) }
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, { $0 * 16 + (map[String($1)] ?? 0xff) })
if total > 0xFF {
assertionFailure("Input char was wrong")
}
return UnicodeScalar(total)
}
最终编辑:解释
鉴于ascii表具有所有数字(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
相同
'2'是2,'F'是15(前面的例子),对吗?由于hex是16,我们需要做:
((16 ^ 1) * 2) + ((16 ^ 0) * 15) = 47
干得好:
var string = String(UnicodeScalar(Int("2C", radix: 16)!))
顺便说一句,您可以在文字字符串中包含十六进制值,如下所示:
var string = "\u{2c}"
使用Swift 5,您必须将字符串变量转换为整数(使用init(_:radix:)
初始化程序),从此整数创建Unicode标量(使用init(_:)
),然后从此Unicode标量(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()
结果:,