我想念易于使用的字符串函数,这些函数易于使用,而无需键入奇怪的标识符行。因此,我决定建立一个包含有用且可识别的String函数的库。
我首先尝试使用可可字符串函数来解决此问题。所以我在操场上尝试了:
import Cocoa
func PartOfString(s: String, start: Int, length: Int) -> String
{
return s.substringFromIndex(advance(s.startIndex, start - 1)).substringToIndex(advance(s.startIndex, length))
}
PartOfString("HelloaouAOUs.World", 1, 5) --> "Hello"
PartOfString("HelloäöüÄÖÜß…World", 1, 5) --> "Hello"
PartOfString("HelloaouAOUs.World", 1, 18) --> "HelloaouAOUs.World"
PartOfString("HelloäöüÄÖÜß…World", 1, 18) --> "HelloäöüÄÖÜß…World"
PartOfString("HelloaouAOUs.World", 6, 7) --> "aouAOUs"
PartOfString("HelloäöüÄÖÜß…World", 6, 7) --> "äöüÄO"
如果案例的字符串中包含UnCode Characters,则该“ substringFromIndex”不是起始索引。更糟糕的是,如果在字符串中包含UnCode字符,则Swift程序有时会在运行时崩溃,在这种情况下,“ substringFromIndex”不是Start-Index。因此,我决定创建一组新的函数,以解决此问题并与UnCode-Characters一起使用。请注意,文件名也可以包含UnCode-Characters。因此,如果您认为不需要UnCode字符,那就错了。
如果要重现此问题,则需要与我使用的相同的String,因为从此Web页进行复制不会重现此问题。
var s: String = "HelloäöüÄÖÜß…World"
var t: String = s.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
var u: String = "Helloa%CC%88o%CC%88u%CC%88A%CC%88O%CC%88U%CC%88%C3%9F%E2%80%A6World".stringByRemovingPercentEncoding!
var b: Bool = (s == u) --> true
PartOfString(s, 6, 7) --> "äöüÄO"
现在您可以了解一下,使用以下功能将令人烦恼的Canonical-Mapping UniCode转换为兼容的代码:
func percentescapesremove (s: String) -> String
{
return (s.stringByRemovingPercentEncoding!.precomposedStringWithCompatibilityMapping)
}
您将得到的结果是:
var v: String = percentescapesremove(t) --> "HelloäöüÄÖÜß...World"
PartOfString(v, 6, 7) --> "äöüÄÖÜß"
var a: Bool = (s == v) --> false
这样做时,“äöüÄÖÜß”看起来不错,您认为一切都很好,但是请查看已从UniCode“ ...”永久转换为非UniCode“ ...”的“ ...”,并得到结果与第一个字符串不同。如果您具有UniCode文件名,则转换将导致在卷上找不到文件。因此,最好仅将其转换为scree输出,然后将原始String保留在保存位置。
上面的PartOfString-Function的问题是,它在赋值的第一部分中生成了一个新的String,并使用该旧String的索引作为旧字符串的索引,这是行不通的,因为UniCode的长度与普通字母。因此,我改善了功能(感谢Martin R的帮助):
func NewPartOfString(s: String, start: Int, length: Int) -> String
{
let t: String = s.substringFromIndex(advance(s.startIndex, start - 1))
return t.substringToIndex(advance(t.startIndex, length))
}
结果是正确的:
NewPartOfString("HelloaouAOUs.World", 1, 5) --> "Hello"
NewPartOfString("HelloäöüÄÖÜß…World", 1, 5) --> "Hello"
NewPartOfString("HelloaouAOUs.World", 1, 18) --> "HelloaouAOUs.World"
NewPartOfString("HelloäöüÄÖÜß…World", 1, 18) --> "HelloäöüÄÖÜß…World"
NewPartOfString("HelloaouAOUs.World", 6, 7) --> "aouAOUs"
NewPartOfString("HelloäöüÄÖÜß…World", 6, 7) --> "äöüÄÖÜß"
在下一步中,我将展示一些可以使用并正常工作的功能。所有这些都基于Integer-Index-Values,该值将从第一个字符结束处的1开始,最后一个字符的索引与String的长度相同。
此函数返回字符串的长度:
func len (s: String) -> Int
{
return (countElements(s)) // This works not really fast, because of UniCode
}
此函数返回字符串中第一个UniCode字符的UniCode编号:
func asc (s: String) -> Int
{
if (s == "")
{
return 0
}
else
{
return (Int(s.unicodeScalars[s.unicodeScalars.startIndex].value))
}
}
此函数返回给定UniCode编号的UniCode字符:
func char (c: Int) -> String
{
var s: String = String(UnicodeScalar(c))
return (s)
}
此函数返回字符串的大写表示形式:
func ucase (s: String) -> String
{
return (s.uppercaseString)
}
此函数返回字符串的小写形式表示形式:
func lcase (s: String) -> String
{
return (s.lowercaseString)
}
下一个函数给出具有给定长度的字符串的左侧部分:
func left (s: String, length: Int) -> String
{
if (length < 1)
{
return ("")
}
else
{
if (length > len(s))
{
return (s)
}
else
{
return (s.substringToIndex(advance(s.startIndex, length)))
}
}
}
下一个函数给出具有给定长度的字符串的右侧部分:
func right (s: String, laenge: Int) -> String
{
var L: Int = len(s)
if (L <= laenge)
{
return(s)
}
else
{
if (laenge < 1)
{
return ("")
}
else
{
let t: String = s.substringFromIndex(advance(s.startIndex, L - laenge))
return t.substringToIndex(advance(t.startIndex, laenge))
}
}
}
下一个函数给出具有给定长度的String部分:
func mid (s: String, start: Int, laenge: Int) -> String
{
if (start <= 1)
{
return (left(s, laenge))
}
else
{
var L: Int = len(s)
if ((start > L) || (laenge < 1))
{
return ("")
}
else
{
if (start + laenge > L)
{
let t: String = s.substringFromIndex(advance(s.startIndex, start - 1))
return t.substringToIndex(advance(t.startIndex, L - start + 1))
}
else
{
let t: String = s.substringFromIndex(advance(s.startIndex, start - 1))
return t.substringToIndex(advance(t.startIndex, laenge))
}
}
}
}
更加困难的是在给定位置获得字符,因为我们不能将“ substringFromIndex”和“ substringToIndex”与“ substringFromIndex”一起使用而不是起始索引。因此,想法是逐字逐字地查找字符串,并获取所需的子字符串。
func CharacterOfString(s: String, index: Int, length: Int) -> String
{
var c: String = ""
var i: Int = 0
for UniCodeChar in s.unicodeScalars
{
i = i + 1
if ((i >= index) && (i < index + length))
{
c = c + String(UniCodeChar)
}
}
return (c)
}
但这对于包含UniCode字符的字符串不正确。以下示例显示了发生的情况:
CharacterOfString("Swift Example Text aouAOUs.", 16, 8) --> "ext aouA"
len(CharacterOfString("Swift Example Text aouAOUs.", 16, 8)) --> 8
CharacterOfString("Swift Example Text äöüÄÖÜß…", 16, 8) --> "ext äö"
len(CharacterOfString("Swift Example Text äöüÄÖÜß…", 16, 8)) --> 6
因此,我们看到结果字符串很短,因为UniCode-Character可以包含多个字符。这是因为“ä”可以是一个UniCode字符,也可以写成两个“ a” UniCode字符。因此,我们需要另一种方法来获取有效的子字符串。
解决方案是将UniCode-String转换为UniCode-Characters数组,并使用该数组的索引获取有效字符。在所有情况下,这都能在给定的索引下获得UniCode-String的单个字符:
func indchar (s: String, i: Int) -> String
{
if ((i < 1) || (i > len(s)))
{
return ("")
}
else
{
return String(Array(s)[i - 1])
}
}
以此知识为基础,我构建了一个函数,该函数可以使用给定的Start-Index和给定的长度来获取有效的UniCode-Substring:
func substring(s: String, Start: Int, Length: Int) -> String
{
var L: Int = len(s)
var UniCode = Array(s)
var result: String = ""
var TheEnd: Int = Start + Length - 1
if ((Start < 1) || (Start > L))
{
return ("")
}
else
{
if ((Length < 0) || (TheEnd > L))
{
TheEnd = L
}
for var i: Int = Start; i <= TheEnd; ++i
{
result = result + String(UniCode[i - 1])
}
return (result)
}
}
下一个函数在另一个字符串中搜索给定字符串的位置:
func position (original: String, search: String, start: Int) -> Int
{
var index = part(original, start).rangeOfString(search)
if (index != nil)
{
var pos: Int = distance(original.startIndex, index!.startIndex)
return (pos + start)
}
else
{
return (0)
}
}
如果给定的字符代码为数字(0-9),则此函数看起来如下:
func number (n: Int) -> Bool
{
return ((n >= 48) & (n <= 57)) // "0" to "9"
}
现在显示了基本的字符串操作,但是数字呢?数字将如何转换为字符串,反之亦然?让我们看一下将字符串转换为数字的方法。请不要“!” 在第二行中,它用于获取一个Int而不是一个可选的Int。
var s: String = "123" --> "123"
var v: Int = s.toInt() --> (123)
var v: Int = s.toInt()! --> 123
但是,如果String包含一些字符,则此方法不起作用:
var s: String = "123." --> "123."
var v: Int = s.toInt()! --> Will result in a Runtime Error, because s.toInt() = nil
因此,我决定构建一个Smater函数来获取String的值:
func val (s: String) -> Int
{
var p: Int = 0
var sign: Int = 0
if (indchar(s, 1) == "-")
{
sign = 1
p = 1
}
while(number(asc(indchar(s, p + 1))))
{
p = p + 1
}
if (p > sign)
{
return (left(s, p).toInt()!)
}
else
{
return (0)
}
}
现在结果是正确的,并且不会产生Runtime-Error:
var s: String = "123." --> "123."
var v: Int = val(s) --> 123
现在浮点数也一样:
func realval (s: String) -> Double
{
var r: Double = 0
var p: Int = 1
var a: Int = asc(indchar(s, p))
if (indchar(s, 1) == "-")
{
p = 2
}
while ((a != 44) && (a != 46) && ((a >= 48) & (a <= 57)))
{
p = p + 1
a = asc(indchar(s, p))
}
if (p >= len(s)) // Integer Number
{
r = Double(val(s))
}
else // Number with fractional part
{
var mantissa: Int = val(substring(s, p + 1, -1))
var fract: Double = 0
while (mantissa != 0)
{
fract = (fract / 10) + (Double(mantissa % 10) / 10)
mantissa = mantissa / 10
p = p + 1
}
r = Double(val(s)) + fract
p = p + 1
}
a = asc(indchar(s, p))
if ((a == 69) || (a == 101)) // Exponent
{
var exp: Int = val(substring(s, p + 1, -1))
if (exp != 0)
{
for var i: Int = 1; i <= abs(exp); ++i
{
if (exp > 0)
{
r = r * 10
}
else
{
r = r / 10
}
}
}
}
return (r)
}
这适用于具有指数的浮点数:
var s: String = "123.456e3"
var t: String = "123.456e-3"
var v: Double = realval(s) --> 123456
var w: Double = realval(t) --> 0.123456
从整数生成字符串要简单得多:
func str (n: Int) -> String
{
return (String(n))
}
浮点变量的字符串不适用于String(n),但可以使用以下方法完成:
func strreal (n: Double) -> String
{
return ("\(n)")
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句