➽02字符串与字符

Posted itzyjr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了➽02字符串与字符相关的知识,希望对你有一定的参考价值。

字符串字面值

let someString = "Some string literal value"

多行字符串字面值

let quotation = """
The White Rabbit put on his spectacles.  "Where shall I begin,
please your Majesty?" he asked.

"Begin at the beginning," the King said gravely, "and go on
till you come to the end; then stop."
"""

以下两条字符串是相同的:

let singleLineString = "These are the same."
let multilineString = """
These are the same.
"""

当源代码在多行字符串文字中包含换行符时,该换行符也会出现在字符串的值中。如果希望使用换行符使源代码更易于阅读,但不希望换行符成为字符串值的一部分,请在这些行的末尾写一个反斜杠(\\):

let softWrappedQuotation = """
The White Rabbit put on his spectacles.  "Where shall I begin, \\
please your Majesty?" he asked.

"Begin at the beginning," the King said gravely, "and go on \\
till you come to the end; then stop."
"""

要生成以换行符开头或结尾的多行字符串文字,请在第一行或最后一行写一个空行。例如:

let lineBreaks = """

This string starts with a line break.
It also ends with a line break.

"""

多行字符串可以缩进以匹配周围的代码。结束引号(""")前的空格告诉Swift在所有其他行之前忽略哪些空格。但是,如果您在结束引号前的空格之外在行首写入空格,则该空格将被包括在内。

特殊字符
转义的特殊字符\\0(空字符),\\(反斜杠),\\t(水平制表符),\\n(换行符),\\r(回车符),"(双引号)和’(单引号)是一个任意的Unicode标量值,写为\\u{n},其中n是一个1-8位的十六进制数。

let wiseWords = "\\"Imagination is more important than knowledge\\" - Einstein"
// "Imagination is more important than knowledge" - Einstein
let dollarSign = "\\u{24}"        // $,  Unicode scalar U+0024
let blackHeart = "\\u{2665}"      // ♥,  Unicode scalar U+2665
let sparklingHeart = "\\u{1F496}" // 💖, Unicode scalar U+1F496

由于多行字符串文字使用三个双引号而不是一个双引号,因此可以在多行字符串文字中包含双引号("),而无需转义。若要在多行字符串中包含文本:""",则至少要转义一个引号。例如:

let threeDoubleQuotationMarks = """
Escaping the first quotation mark \\"""
Escaping all three quotation marks \\"\\"\\"
"""

扩展的字符串分隔符
可以在扩展分隔符中放置字符串文字,以便在字符串中包含特殊字符,而无需调用其效果。例如,打印字符串文字#"Line 1\\nLine 2"#打印换行转义序列(\\n),而不是跨两行打印字符串。例如,如果字符串为#"Line 1\\nLine 2"#,并且希望打断该行,则可以使用#"Line 1\\#nLine 2"#。类似地,###"Line1\\###nLine2"###也完成打断行。

使用扩展分隔符创建的字符串文字也可以是多行字符串文字。您可以使用扩展分隔符在多行字符串中包含文本:""",从而覆盖以文本结尾的默认行为。例如:

let threeMoreDoubleQuotationMarks = #"""
Here are three more double quotes: """
"""#

初始化一个空字符串

var emptyString = ""// empty string literal
var anotherEmptyString = String()// initializer syntax
// 这两个字符串都为空, 它们是等效的
if emptyString.isEmpty {// 用isEmpty判断空否
	print("Nothing to see here")// printed
}

字符串易变性

var variableString = "Horse"
variableString += " and carriage"
// variableString is now "Horse and carriage"

let constantString = "Highlander"
constantString += " and another Highlander"
// this reports a compile-time ERROR! - a constant string cannot be modified

字符串是值类型
Swift的字符串类型是值类型。如果创建新的字符串值,则在将该字符串值传递给函数或方法时,或在将其分配给常量或变量时,会复制该字符串值。在每种情况下,都会创建现有字符串值的新副本,并传递或分配新副本,而不是原始版本

Swift的默认复制字符串行为确保当函数或方法传递字符串值时,无论字符串值来自何处,您都清楚地拥有该字符串值。您可以确信传递的字符串不会被修改,除非您自己修改它。
在幕后,Swift的编译器优化了字符串的使用,以便只有在绝对必要时才进行实际复制。这意味着您在使用字符串作为值类型时总是可以获得很好的性能。

字符

for character in "Dog!🐶" {
	print(character)
}
// D
// o
// g
// !
// 🐶

或者,可以通过提供字符类型注释,从单个字符串文字创建独立的字符常量或变量:

let exclamationMark: Character = "!"

通过将字符值数组作为参数传递给初始值设定项,可以构造字符串值:

let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"]
let catString = String(catCharacters)// 通过字符数组构造字符串
print(catString)// Cat!🐱

连接字符串与字符

let string1 = "hello"
let string2 = " there"
var welcome = string1 + string2// "hello there"
welcome += string2// "hello there there"

可以使用String类型的append()方法,添加字符:

let exclamationMark: Character = "!"
welcome.append(exclamationMark)// "hello there there!"

不能将字符串或字符附加到现有字符变量,因为字符值只能包含单个字符。

如果使用多行字符串文字来构建较长字符串的行,则希望字符串中的每一行都以换行符结束,包括最后一行。例如:

let badStart = """
one
two
"""
let end = """
three
"""
print(badStart + end)
// 打印两行:
// one
// twothree

let goodStart = """
one
two

"""
print(goodStart + end)
// 打印三行:
// one
// two
// three

字符串插值
字符串插值是一种通过将常量、变量、文本和表达式的值包含在字符串文本中,从而从它们的组合中构造新字符串值的方法。可以在单行和多行字符串文字中使用字符串插值。插入到字符串文字中的每一项都用一对括号括起来,以反斜杠(\\)为前缀:

let multiplier = 3
let message = "\\(multiplier) times 2.5 is \\(Double(multiplier) * 2.5)"
// message is "3 times 2.5 is 7.5"

可以使用扩展字符串分隔符创建包含字符的字符串,否则这些字符将被视为字符串插值。例如:

print(#"Write an interpolated string in Swift using \\(multiplier)."#)
// Prints "Write an interpolated string in Swift using \\(multiplier)."

在使用扩展分隔符的字符串中使用字符串插值。例如:

print(#"6 times 7 is \\#(6 * 7)."#)
// Prints "6 times 7 is 42."

Unicode
Unicode是在不同书写系统中编码、表示和处理文本的国际标准。它使您能够以标准化的形式表示任何语言中的几乎任何字符,并在文本文件或网页等外部源中读取和写入这些字符。Swift的字符串和字符类型完全符合Unicode,如本节所述。

Unicode标量值
在幕后,Swift的原生字符串类型是从Unicode标量值构建的。Unicode标量值是字符或修饰符的唯一 21-bit 数字,如U+0061表示拉丁小写字母A(“a”),或U+1F425表示正面小鸡(“🐥”)。

请注意,并非所有21位Unicode标量值都分配给一个字符。有些标量保留供将来分配或在UTF-16编码中使用。已指定给字符的标量值通常也有名称,如上面示例中的拉丁字母a和正面小鸡。

扩展字形簇
Swift字符类型的每个实例都表示一个扩展的字形簇。扩展的字形簇是一个或多个Unicode标量的序列,它们(在组合时)生成单个人类可读字符。

这里有一个例子。字母é可以表示为单个Unicode标量é(带锐音符的拉丁文小写字母E,或U+00E9)。但是,同一个字母也可以表示为一对标量——一个标准字母e(拉丁文小写字母e,或U+0065),后跟组合的锐重音标量(U+0301)。组合的锐重音标量以图形方式应用于它前面的标量,当它由支持Unicode的文本呈现系统呈现时,将e转换为é。

在这两种情况下,字母é都表示为单个Swift字符值,表示扩展的字形簇。在第一种情况下,簇包含一个标量;在第二种情况下,它是由两个标量组成的簇:

let eAcute: Character = "\\u{E9}"// é
let combinedEAcute: Character = "\\u{65}\\u{301}"// e followed by  ́ also is é

扩展的字形簇是一种灵活的方法,可以将许多复杂的脚本字符表示为单个字符值。例如,韩国语字母表中的韩语音节可以表示为预合成或分解序列。在Swift中,这两种表示形式都符合单个字符值的条件:

let precomposed: Character = "\\u{D55C}"// 한
let decomposed: Character = "\\u{1112}\\u{1161}\\u{11AB}"// ᄒ, ᅡ, ᆫ also is 한

扩展的字形簇允许用于封闭标记的标量(例如结合封闭的圆或U+20DD)将其他Unicode标量封闭为单个字符值的一部分:

let enclosedEAcute: Character = "\\u{E9}\\u{20DD}"// é⃝

区域指标符号的Unicode标量可以成对组合以形成单个字符值,例如区域指标符号字母U(U+1F1FA)和区域指标符号字母S(U+1F1F8)的组合:

let regionalIndicatorForUS: Character = "\\u{1F1FA}\\u{1F1F8}"// 🇺🇸

字符计数

let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"
print("unusualMenagerie has \\(unusualMenagerie.count) characters")
// Prints "unusualMenagerie has 40 characters"

请注意,Swift对字符值使用扩展的字形簇意味着字符串连接和修改可能并不总是影响字符串的字符计数。

例如,如果您使用四个字符的单词cafe初始化一个新字符串,然后在该字符串的末尾附加一个组合急性重音(U+0301),则生成的字符串的字符计数仍然为4,第四个字符为é,而不是e:

var word = "cafe"
print("the number of characters in \\(word) is \\(word.count)")
// Prints "the number of characters in cafe is 4"

word += "\\u{301}"    // COMBINING ACUTE ACCENT, U+0301

print("the number of characters in \\(word) is \\(word.count)")
// Prints "the number of characters in café is 4"

扩展的字形簇可以由多个Unicode标量组成。这意味着不同的字符和同一字符的不同表示可能需要不同的内存量来存储。因此,Swift中的每个字符在字符串表示中占用的内存量并不相同。因此,如果不遍历字符串以确定其扩展的字形簇边界,就无法计算字符串中的字符数。如果使用的是特别长的字符串值,请注意count属性必须迭代整个字符串中的Unicode标量,以便确定该字符串的字符。
count属性返回的字符计数并不总是与包含相同字符的NSString的length属性相同。NSString的长度基于字符串的UTF-16表示中的16位代码单元数,而不是字符串中的Unicode扩展字形簇数。

访问和修改字符串
使用startIndex属性访问字符串第一个字符的位置。endIndex属性是字符串中最后一个字符之后的位置。因此,endIndex属性不是字符串下标的有效参数。如果字符串为空,则startIndex和endIndex相等。

可以使用String的index(before:)index(after:)方法访问给定索引前后的索引。要访问距离给定索引较远的索引,可以使用index(_:offsetBy:)方法,而不是多次调用其中一个方法。

let greeting = "Guten Tag!"
greeting[greeting.startIndex]// G

greeting[greeting.index(before: greeting.endIndex)]// !

greeting[greeting.index(after: greeting.startIndex)]// u

let index = greeting.index(greeting.startIndex, offsetBy: 7)
greeting[index]// a
greeting[greeting.endIndex] // Error
greeting.index(after: greeting.endIndex) // Error

使用indices属性访问字符串中单个字符的所有索引。

for index in greeting.indices {
	print("\\(greeting[index]) ", terminator: "")// "G u t e n  T a g ! "
}

默认来说,print()函数通过在行末尾添加换行符来结束输出。要想输出不带换行符的值,那就传一个空的换行符作为结束——比如,print(someValue, terminator: "")。

可以在符合Collection协议的任何类型上使用startIndex和endIndex属性以及index(before:)、index(after:)和index(_:offsetBy:)方法。这包括字符串,以及集合类型,如Array、Dictionary和Set。

插入和删除
若要在指定索引处向字符串中插入单个字符,请使用insert(_:at:)方法;若要在指定索引处插入另一个字符串的内容,请使用insert(contentsOf:at:)方法。

var welcome = "hello"
welcome.insert("!", at: welcome.endIndex)// "hello!"

welcome.insert(contentsOf: " there", at: welcome.index(before: welcome.endIndex))// "hello there!"

要从指定索引处的字符串中删除单个字符,请使用remove(at:)方法;要删除指定范围内的子字符串,请使用removeSubrange(_:)方法:

welcome.remove(at: welcome.index(before: welcome.endIndex))// "hello there"

let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex
welcome.removeSubrange(range)// "hello"

可以对符合RangeReplaceableCollection协议的任何类型使用insert(_:at:), insert(contentsOf:at:), remove(at:)和removeSubrange(_:)方法。这包括字符串,以及集合类型,如Array、Dictionary和Set。

Substrings
与字符串不同,在对字符串执行操作时,子字符串只使用很短的时间。当你准备将结果存储更长时间时,可以将子字符串转换为字符串的实例。例如:

let greeting = "Hello, world!"
let index = greeting.firstIndex(of: ",") ?? greeting.endIndex
let beginning = greeting[..<index]// "Hello"  它重用了greeting使用的内存

// Convert the result to a String for long-term storage.
let newString = String(beginning)// 它是从子字符串创建的,有自己的存储空间

与字符串一样,每个子字符串都有一个存储组成子字符串的字符的内存区域。字符串和子字符串之间的区别在于,作为性能优化,子字符串可以重用用于存储原始字符串的部分内存,或用于存储另一个子字符串的部分内存。(字符串具有类似的优化,但如果两个字符串共享内存,则它们相等。)此性能优化意味着您不必支付复制内存的性能成本,直到您修改字符串或子字符串为止。如上所述,子字符串不适合长期存储,因为它们重复使用原始字符串的存储。只要使用其任何子字符串,整个原始字符串都必须保存在内存中。

在上面的示例中,问候语是一个字符串,这意味着它有一个存储组成字符串的字符的内存区域。因为开头是问候语的一个子串,所以它重用了问候语使用的内存。相反,newString是一个字符串,当它从子字符串创建时,它有自己的存储空间。下图显示了这些关系:

字符串和子字符串都符合StringProtocol协议,这意味着字符串操作函数通常可以方便地接受StringProtocol值。可以使用字符串或子字符串值调用此类函数。

比较字符串

let quotation = "We're a lot alike, you and I."
let sameQuotation = "We're a lot alike, you and I."
if quotation == sameQuotation {
    print("These two strings are considered equal")// printed
}

如果扩展的字形簇具有相同的语言含义和外观,即使它们在幕后由不同的Unicode标量组成,它们在规范上是等价的。

// "Voulez-vous un café?" using LATIN SMALL LETTER E WITH ACUTE
let eAcuteQuestion = "Voulez-vous un caf\\u{E9}?"

// "Voulez-vous un café?" using LATIN SMALL LETTER E and COMBINING ACUTE ACCENT
let combinedEAcuteQuestion = "Voulez-vous un caf\\u{65}\\u{301}?"

if eAcuteQuestion == combinedEAcuteQuestion {
    print("These two strings are considered equal")// printed
}

相反,英语中使用的拉丁文大写字母A(U+0041,或"A")与俄语中使用的西里尔文大写字母A(U+0410,或"A")并不等同。这些字符在视觉上相似,但语言含义不同:

let latinCapitalLetterA: Character = "\\u{41}"

let cyrillicCapitalLetterA: Character = "\\u{0410}"

if latinCapitalLetterA != cyrillicCapitalLetterA {
    print("These two characters aren't equivalent.")// printed
}

前缀和后缀相等
若要检查字符串是否具有特定的字符串前缀或后缀,请调用该字符串的hasPrefix(_:)hasSuffix(_:)方法,这两种方法都采用String类型的单个参数并返回布尔值。

let romeoAndJuliet = [
    "Act 1 Scene 1: Verona, A public place",
    "Act 1 Scene 2: Capulet's mansion",
    "Act 1 Scene 3: A room in Capulet's mansion",
    "Act 1 Scene 4: A street outside Capulet's mansion",
    "Act 1 Scene 5: The Great Hall in Capulet's mansion",
    "Act 2 Scene 1: Outside Capulet's mansion",
    "Act 2 Scene 2: Capulet's orchard",
    "Act 2 Scene 3: Outside Friar Lawrence's cell",
    "Act 2 Scene 4: A street in Verona",
    "Act 2 Scene 5: Capulet's mansion",
    "Act 2 Scene 6: Friar Lawrence's cell"
]
var act1SceneCount = 0
for scene in romeoAndJuliet {
    if scene.hasPrefix("Act 1 ") {
        act1SceneCount += 1
    }
}
print("There are \\(act1SceneCount) scenes in Act 1")
//=> "There are 5 scenes in Act 1"
var mansionCount = 0
var cellCount = 0
for scene in romeoAndJuliet {
    if scene.hasSuffix("Capulet's mansion") {
        mansionCount += 1
    } else if scene.hasSuffix("Friar Lawrence's cell") {
        cellCount += 1
    }
}
print("\\(mansionCount) mansion scenes; \\(cellCount) cell scenes")
//=> "6 mansion scenes; 2 cell scenes"

字符串的Unicode表示
将Unicode字符串写入文本文件或其他存储时,该字符串中的Unicode标量将以几种Unicode定义的编码形式之一进行编码。每个表单以称为代码单元的小块对字符串进行编码。这些包括UTF-8编码格式(将字符串编码为8位代码单元)、UTF-16编码格式(将字符串编码为16位代码单元)和UTF-32编码格式(将字符串编码为32位代码单元)。

Swift提供了几种不同的方法来访问字符串的Unicode表示形式。您可以使用for in语句对字符串进行迭代,以将其单个字符值作为Unicode扩展的字形簇进行访问。

或者,访问其他三种符合Unicode的表示形式之一中的字符串值:
● UTF-8代码单元的集合(使用字符串的utf8属性访问)
● UTF-16代码单元的集合(使用字符串的utf16属性访问)
● 21位Unicode标量值的集合,相当于字符串的UTF-32编码形式(使用字符串的unicodeScalars属性访问)

下面的每个示例都显示了以下字符串的不同表示形式,该字符串由字符D、o、g、!!(双感叹号或Unicode标量U+203C)和🐶 字符(狗脸或Unicode标量U+1F436):

let dogString = "Dog!!🐶"

UTF-8表示
通过迭代字符串的utf8属性,可以访问字符串的UTF-8表示形式。此属性的类型为String.UTF8View,它是无符号8位(UInt8)值的集合,字符串UTF-8表示形式中的每个字节对应一个值:

for codeUnit in dogString.utf8 {
    print("\\(codeUnit) ", terminator: "")
}
print("")
// Prints "68 111 103 226 128 188 240 159 144 182 "

在上面的示例中,前三个十进制代码单位值(68,111,103)表示字符D、o和g,其UTF-8表示与ASCII表示相同。接下来的三个十进制代码单位值(226、128、188)是双感叹号字符的三字节UTF-8表示形式。最后四个代码单位值(240、159、144、182)是狗脸字符的四字节UTF-8表示。

UTF-16表示
通过迭代字符串的utf16属性,可以访问字符串的UTF-16表示形式。此属性的类型为String.UTF16View,它是无符号16位(UInt16)值的集合,在字符串的UTF-16表示中,每个16位代码单元对应一个值:

for codeUnit in dogString.utf16 {
    print("\\(codeUnit) ", terminator: "")
}
print("")
// Prints "68 111 103 8252 55357 56374 "

Unicode标量表示
可以通过迭代字符串的Unicode的unicodeScalars属性来访问字符串值的Unicode标量表示。此属性的类型为UnicodeScalarView,它是UnicodeScalar类型的值的集合。
每个UnicodeScalar都有一个value属性,返回标量的21位值,在UInt32值中表示:

for scalar in dogString.unicodeScalars {
    print("\\(scalar.value) ", terminator: "")
}
print("")
// Prints "68 111 103 8252 128054 "

前三个UnicodeScalar值(68,111,103)的值属性再次表示字符D、o和g。
第四个codeUnit值(8252)也是十六进制值203C的十进制等效值,它表示双感叹号字符的Unicode标量U+203C。
第五个也是最后一个UnicodeScalar(128054)的value属性是十六进制值1F436的十进制等价物,它表示狗脸字符的Unicode标量U+1F436。

作为查询其值属性的替代方法,每个UnicodeScalar值也可用于构造新的字符串值,例如使用字符串插值:

for scalar in dogString.unicodeScalars {
    print("\\(scalar) ")
}
// D
// o
// g
// ‼
// 🐶

以上是关于➽02字符串与字符的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript 代码片段

我的javascript片段返回“非法字符”

python+spark程序代码片段

Regexp_substr 将字符串解析成片段

OAuth2:查询字符串与片段

JQuery02