Search code examples
swifthexascii

Given a hexadecimal string in Swift, convert to hex value


Suppose I am given a string like this:

D7C17A4F

How do I convert each individual character to a hex value?

So D should be 0xD, 7 should be 0x7

Right now, I have each individual character represented as it's ASCII value. D is 68, 7 is 55. I'm trying to pack those two values into one byte. For example: D7 becomes 0xD7 and C1 becomes 0xC1. I can't do that using the ASCII decimal values though.


Solution

  • A possible solution:

    let string = "D7C17A4F"
    
    let chars = Array(string)
    let numbers = map (stride(from: 0, to: chars.count, by: 2)) {
        strtoul(String(chars[$0 ..< $0+2]), nil, 16)
    }
    

    Using the approach from https://stackoverflow.com/a/29306523/1187415, the string is split into substrings of two characters. Each substring is interpreted as a sequence of digits in base 16, and converted to a number with strtoul().

    Verify the result:

    println(numbers)
    // [215, 193, 122, 79]
    
    println(map(numbers, { String(format: "%02X", $0) } ))
    // [D7, C1, 7A, 4F]
    

    Update for Swift 2 (Xcode 7):

    let string = "D7C17A4F"
    let chars = Array(string.characters)
    
    let numbers = 0.stride(to: chars.count, by: 2).map {
        UInt8(String(chars[$0 ..< $0+2]), radix: 16) ?? 0
    }
    
    print(numbers) 
    

    or

    let string = "D7C17A4F"
    
    var numbers = [UInt8]()
    var from = string.startIndex
    while from != string.endIndex {
        let to = from.advancedBy(2, limit: string.endIndex)
        numbers.append(UInt8(string[from ..< to], radix: 16) ?? 0)
        from = to
    }
    
    print(numbers) 
    

    The second solution looks a bit more complicated but has the small advantage that no additional chars array is needed.