如何在Swift中进行字符串编程

jscom

我想念易于使用的字符串函数,这些函数易于使用,而无需键入奇怪的标识符行。因此,我决定建立一个包含有用且可识别的String函数的库。

jscom

我首先尝试使用可可字符串函数来解决此问题。所以我在操场上尝试了:

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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在 Pyspark 中进行字符串算术运算

如何在SQL中进行子字符串计算?

如何在pyspark中进行字符串转换?

如何在Elasticsearch中进行字符串搜索?

如何在JavaScript中进行字符串插值?

如何在 CloudBuild 中进行字符串比较?

如何在here字符串中进行变量替换

如何在 SQL 中进行字符串转换?

如何在字符串变量 XSLT 中进行替换?

如何在python中进行模糊字符串更新

如何在 React 的字符串变量中进行字符串插值?

如何在Swift中进行闭包从字符串中提取两个整数以执行计算

如何在Swift中进行子串

如何在Swift中对字符串的行进行排序?

如何在Makefile中使用cat创建的变量中进行字符串替换?

如何在芭蕾舞演员Lang中进行字符串填充

如何在角度标记中进行空/未定义的安全字符串比较?

如何在YAML多行字符串中进行Unicode转义?

如何在JavaScript中的while循环中进行字符串比较

如何在SQL Server 2008中进行布尔字符串比较

ansible:如何在提示中进行字符串插值?

如何在MySql JSON字符串中进行正则表达式

如何在JavaScript中进行字符串替换以将“ 9.61”转换为“ 9:61”?

如何在JavaScript中进行“原始”字符串搜索和替换,而不使用REGEX

如何在Firebase数据库中的字符串中进行简单搜索?

如何在休息操作中进行字符串插值

如何在Oracle中进行TRIM仅从字符串返回大写字母

如何在多个查询中进行多个字符串替换?

如何在 f# 中进行非标准字符串替换?