Wow. Swift makes it really fiddly to copy a substring from a simple String.
Most programming languages allow characters to be simply indexed by their integer position in the string, making targeting a character or a range a matter of simple maths. Because Swift allows a wide range of characters to be used with various bit depths, a precise (memory?) index for each character has to be found first, based its position from the start or end of the string. These positions can then be passed into a method of the String class that returns the substring in the range. I've written a function to do the work:
//arguments: The parent string, number of chars from 1st char in it and total char length of substring
func subStr(str: String, c1: Int, c2: Int) -> String {
//get string indexes for range of substring based on args
let ind1 = str.startIndex.advancedBy(c1)
let ind2 = str.startIndex.advancedBy(c1+c2)
//calls substring function with a range object passed as an argument set to the index values
let sub = str.substringWithRange(Range<String.Index>(start: ind1, end: ind2))
//substring returned
return sub
}
The problem is that because the substringWithRange function only works with Range objects its not obvious how to check if the substring is out of bounds of the string. For example calling this function would produce an error:
subStr ("Stack Overflow", c1: 6, c2: 12)
The c1 argument is OK but the length of the (c2) substring exceeds the upper boundary of the parent string causing a fatal error.
How do I refine this function to make it handle bad arguments or otherwise refine this clunky process?
Many thanks for reading.
You can use
let ind1 = str.startIndex.advancedBy(c1, limit: str.endIndex)
let ind2 = str.startIndex.advancedBy(c1+c2, limit: str.endIndex)
to advance the start index by the given amounts, but not beyond the end index of the string. With that modification, your function gives
subStr ("Stack Overflow", c1: 6, c2: 12) // "Overflow"
subStr ("Stack Overflow", c1: 12, c2: 20) // ""
I quickly made a nice substring function for String
s without Foundation dependency:
extension String {
func substring(from: Int, length: Int) -> String {
return String(dropFirst(from).prefix(length))
}
}
If the length is bigger than possible, it just gives all the characters to the end. Can't crash Can't crash as long as neither argument is negative (it makes sense to crash if any argument is negative since that would be a major flaw in your code).
Example usage:
"Stack Overflow".substring(from: 6, length: 12)
gives
"Overflow"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With