티스토리 뷰
Strings and Characters — The Swift Programming Language (Swift 5.5)
Strings and Characters A string is a series of characters, such as "hello, world" or "albatross". Swift strings are represented by the String type. The contents of a String can be accessed in various ways, including as a collection of Character values. Swi
docs.swift.org
1차 수정 (2022 / 02 / 25) : 의역, 오타 및 스타일 수정
Strings and Characters
문자열(String)은 "hello, world" 또는 "albatross"와 같은 일련의 문자입니다. Swift 문자열은 String 타입으로 표시됩니다. 문자열의 내용은 문자 값들의 집합 등 다양한 방법으로 접근할 수 있습니다.
Swift의 String 및 Characters는 코드에서 텍스트를 빠르게 사용할 수 있는 유니코드 호환 방법을 제공합니다. 문자열 생성 및 조작 구문은 C 언어와 유사한 문자열 리터럴 구문을 사용하여 가볍고 읽을 수 있습니다. 문자열 연결은 두 개의 문자열을 + 연산자와 결합하는 것만큼 간단하며, Swift의 다른 값과 마찬가지로 상수(Constant) 또는 변수(Variable) 중 하나를 선택하여 문자열 변환을 관리합니다. 문자열 보간(string interpolation) 이라고 하는 프로세스에서 문자열을 사용하여 상수, 변수, 리터럴 및 식을 더 긴 문자열에 삽입할 수도 있습니다. 표시, 저장 및 출력을 위한 사용자 지정 문자열 값을 쉽게 만들 수 있습니다.
이렇게 간단한 구문에도 불구하고, Swift의 String 타입은 빠르고 현대적인 문자열 구현입니다. 모든 문자열은 인코딩에 독립적인 유니코드 문자로 구성되며 다양한 유니코드 표현에서 이러한 문자에 액세스할 수 있도록 지원합니다.
Swift의 문자열 유형은 Foundation의 NSString 클래스와 연결되어 있습니다. Foundation은 문자열을 확장하여 NSString에 의해 정의된 메서드를 불러옵니다. 즉, Foundation을 가져오는 경우 캐스팅 없이 String의 NSString 메서드에 액세스할 수 있습니다.
String을 Foundation 과 Cocoa 함께 사용하는 것을 더 알고 싶으면 Bridging Between String and NSString 참고하세요.
String Literals (문자열 리터럴)
코드 내에 미리 정의된 문자열 값을 문자열 리터럴로 포함할 수 있습니다. 문자열 리터럴은 큰 따옴표("")로 둘러싸인 문자의 연속입니다.
상수 또는 변수의 초기 값으로 문자열 리터럴을 사용합니다.
let someString = "Some string literal value"
Swift는 someString 가 문자열 리터럴 값으로 초기화되었기 때문에 문자열(String) 타입으로 유추합니다.
Multiline String Literals (여러 줄 문자열 리터럴)
여러 줄에 걸쳐 있는 문자열이 필요한 경우 세 개의 큰 따옴표 (""") 로 둘러싸인 여러 줄의 문자열 리터럴을 사용합니다.
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."
"""
여러 줄 문자열을 주변 코드와 일치하도록 들여쓰기를 할 수 있습니다. 닫히는 따옴표 앞의 공백("")은 다른 모든 줄 앞에 무시해야 하는 공백을 나타냅니다. 그러나 끝 따옴표 앞에 있는 줄에 공백을 추가하면 공백이 포함됩니다.
첫번째 줄과 두번째 줄은 공백이 없습니다. 3번 째줄은 들여쓰기 + 공백이므로 공백이 적용됩니다.
Special Characters in String Literals (문자열 리터럴의 특수 문자)
문자열 리터럴에는 다음과 같은 특수 문자가 포함될 수 있습니다.
- \0 (null character)
- \\ (backslash)
- \t (horizontal tab)
- \n (line feed)
- \r (carriage return)
- \" (double quotation mark)
- \' (single quotation mark)
- 임의의 유니코드 스칼라 값은 ( \u{n})이며, 여기서 n은 1-8자리 16진수 숫자입니다.
여러 줄의 문자열 리터럴은 한 개가 아닌 세 개의 큰 따옴표(""")를 사용하기 때문에 여러 줄의 문자열 리터럴 안에 큰 따옴표(")를 포함할 수 있습니다. 여러 줄 문자열에 "" 텍스트를 포함하려면 따옴표 중 하나 이상에 \(이스케이프)를 사용하십시오. 예를 들어:
let threeDoubleQuotationMarks = """
Escaping the first quotation mark \"""
Escaping all three quotation marks \"\"\"
"""
Extended String Delimiters (확장된 문자열 구분 문자)
확장된 구분 문자(String Delimiters) 내에 문자열 리터럴을 배치하여 해당 효과를 호출하지 않고 문자열에 특수 문자를 포함할 수 있습니다. 따옴표(") 안에 문자열을 넣고 숫자 기호(#)로 둘러쌉니다. 예를 들어 문자열 리터럴 #"Line1 \n Line 2"# 은 문자열을 두 줄로 출력하는 대신 (\n)를 그대로 출력합니다.
print(#"Line 1 \n Line 2"#) // "Line 1 \n Line 2" 출력
print("Line 1 \n Line 2")
// Line 1
// Line 2
// 출력
문자열 리터럴에 있는 문자에 특수 효과가 필요한 경우, 이스케이프 문자(\) 다음에 오는 문자열 내 숫자 기호 수를 일치시킵니다. 예를 들어 문자열이 #"Line1 \n Line 2"# 에서 \n을 기존처럼 줄바꿈으로 사용하고 싶으면 #"Line1 #\n Line 2"# 로 작성하면 됩니다. 즉 문자열 리터럴을 감싼 # 를 \ 앞에 붙여주면 됩니다.
예를 하나 더 들면 ###"Line1\###nLine2"###"도 줄바꿈 이 됩니다.
확장 구분 문자를 사용하여 만든 문자열 리터럴은 여러 줄의 문자열 리터럴일 수도 있습니다. 확장 구분 문자를 사용하여 """ 로 리터럴이 끝나는 기본 동작을 재정의할 수 있습니다. 예를 들어:
let threeMoreDoubleQuotationMarks = #"""
Here are three more double quotes: """
"""#
원래라면 Here are three more double quotes: 이 출력되어야하지만 확장 구분 문자 # 를 사용함으로써 Here are three more double quotes: """ 가 출력됩니다
Initializing an Empty String (빈 문자열 초기화)
더 긴 문자열을 만들기 위한 시작점으로 빈 문자열 값을 만들려면, 변수에 빈 문자열 리터럴""을 할당하거나 이니셜라이저 구문 String()을 사용하여 새 문자열 인스턴스를 초기화합니다.
var emptyString = "" // empty string literal
var anotherEmptyString = String() // initializer syntax
// 두 문자열다 비어있고 똑같은 value 다
isEmpty 프로퍼티를 사용해서 String 값이 비었는지 Boolean을 확인할 수 있습니다.
if emptyString.isEmpty {
print("문자열 비었다")
}
// emptyString.isEmpty == true 이므로
// Prints "문자열 비었다."
String Mutability(문자열 가변성)
특정 문자열을, 변수 variable (수정 가능한 경우)에 할당하여 수정할 수 있는지 또는 상수 constant (수정할 수 없는 경우)에 할당할 수 있는지 여부를 나타냅니다.
var variableString = "Horse"
variableString += " and carriage"
// variableString is now "Horse and carriage"
let constantString = "Highlander"
constantString += " and another Highlander"
// compile-time error - constant 는 수정할 수 없기 때문에
이 접근 방식은 문자열을 변형할 수 있는지 여부를 나타내기 위해 두 클래스(NSString 및 NSMutableString)를 선택하는 Objective-C 및 코코아의 문자열 변형과는 다릅니다.
Strings Are Value Types (문자열은 value 타입이다)
Swift의 String 타입은 Valte type 입니다. 새로운 String 값을 만들면, String이 함수나 메소드에 전달하거나 상수나 변수에 할당될 때 String 값은 복사됩니다. 각각의 경우 기존 String 값의 새 복사본이 만들어지고, 새 복사본이 전달되거나 할당됩니다.
Swift의 기본 문자열 복사(copy-by-default String) 동작은 함수나 메서드가 문자열 값을 전달할 때 문자열 값이 어디서 왔든 상관없이 사용자가 정확한 문자열 값을 소유한다는 것을 보장합니다. 전달된 문자열은 사용자가 직접 수정하지 않는 한 수정되지 않을 것이라고 확신할 수 있습니다.
백그라운드에서 스위프트의 컴파일러는 문자열 사용을 최적화하여 실제 복사가 절대적으로 필요할 때만 수행되도록 합니다. 즉, 문자열을 value type으로 사용할 때 항상 우수한 성능을 얻을 수 있습니다.
Working with Characters (문자 작업)
for-in 루프를 사용하여 문자열의 각각의 문자(Charaters)들에 접근할 수 있습니다.
for character in "Dog!🐶" {
print(character)
}
// D
// o
// g
// !
// 🐶
또는 Character 타입을 사용하여 단일 문자 문자열 리터럴에서 독립 실행형(stand-alone) 문자 상수 또는 변수를 만들 수 있습니다.
let exclamationMark: Character = "!"
일련의 문자 값을 인수로 이니셜라이저에 전달하여 String 값을 구성할 수 있습니다.
let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"]
let catString = String(catCharacters)
print(catString)
// Prints "Cat!🐱"
Concatenating Strings and Characters (문자열과 문자 연결)
문자열 값에 + 를 통해 연결하여 새 문자열 값을 만들 수 있습니다.
let string1 = "hello"
let string2 = " there"
var welcome = string1 + string2
// welcome now equals "hello there"
추가 할당 연산자(+=)를 사용하여 기존 문자열 변수에 문자열 값을 추가할 수도 있습니다.
var instruction = "look over"
instruction += string2
// instruction now equals "look over there"
append() 메소드를 사용하여 String 변수에 character 값을 추가할 수 있습니다.
let exclamationMark: Character = "!"
welcome.append(exclamationMark)
// welcome now equals "hello there!"
문자(Character) 값은 단일 문자만 포함해야 하므로 기존 문자(Character) 변수에는 문자열(Stinrg) 또는 문자(Character)를 추가할 수 없습니다.
여러 줄의 문자열 리터럴을 사용하여 더 긴 문자열의 줄을 작성하는 경우 마지막 줄을 포함하여 문자열의 모든 줄이 줄 바꿈으로 끝나도록 합니다. 예를 들어
let badStart = """
one
two
"""
let end = """
three
"""
print(badStart + end)
// Prints two lines:
// one
// twothree
// 줄 바꿈을 추가해준다
let goodStart = """
one
two
"""
print(goodStart + end)
// Prints three lines:
// one
// two
// three
String Interpolation (문자열 삽입)
문자열 삽입은 상수, 변수, 리터럴 및 식을 문자열 리터럴에 포함시켜 혼합된 상태에서 새 문자열 값을 구성하는 방법입니다. 한 줄 혹은 여러 줄 문자열 리터럴 모두에서 문자열 삽입을 사용할 수 있습니다.
문자열 리터럴에 삽입하는 각 항목은 한 쌍의 괄호 안에 백슬래시(\):
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
// message is "3 times 2.5 is 7.5"
확장 문자열 구분 기호를 사용하여 문자열 보간으로 간주될 문자를 포함하는 문자열을 만들 수 있습니다. 예를 들어:
let result = 6 * 7
print(#"6 times 7 is \#(result)."#)
// Prints "6 times 7 is 42."
print(#"Write an interpolated string in Swift using \(multiplier)."#)
// Prints "Write an interpolated string in Swift using \(multiplier)."
// #로 둘러싸여 있는데 #를 \ 앞에 안 붙여주었으므로 그대로 출력된다.
삽입된 문자열의 괄호 안에 쓰는 식에는 이스케이프되지 않은(unescaped) 백슬래시(\), carriage return 또는 line feed를 포함할 수 없습니다. 그러나 다른 문자열 리터럴을 포함할 수 있습니다.
Unicode (유니코드)
유니코드는 서로 다른 문자 시스템에서 텍스트를 인코딩, 표현 및 처리하기 위한 국제 표준입니다. 이를 통해 모든 언어의 거의 모든 문자를 표준화된 형식으로 나타낼 수 있으며 텍스트 파일이나 웹 페이지와 같은 외부 소스에서 해당 문자를 읽고 쓸 수 있습니다. Swift의 문자열(String) 및 문자 유형(Character)은 완전히 유니코드 호환(Unicode-compliant)입니다.
Unicode Scalar Values (유니코드 스칼라 값)
백그라운드에는 Swift의 기본 문자열 유형이 유니코드 스칼라 값으로 작성됩니다. 유니코드 스칼라 값은 문자와 수정자에 대한 고유한 21비트 숫자입니다. 예를 들어
모든 21비트 유니코드 스칼라 값이 한 문자에 할당되지는 않으며, 일부 스칼라는 향후 할당 또는 UTF-16 인코딩에 사용하도록 예약되어 있습니다. 문자에 할당된 스칼라 값에는 일반적으로 위의 예에서 라틴 작은 문자 A 및 전면 베이비 칙과 같은 이름이 있습니다. U+0061 for 소문자 A ("a"), or U+1F425 for FRONT-ACING BABY CHICK ("🐥")
Extended Grapheme Clusters (확장된 문자소 집합)
Swift의 문자 유형의 모든 인스턴스는 하나의 extended grapheme cluster 를 나타냅니다. extended grapheme cluster는 사람이 읽을 수 있는 단일 문자를 생성하는 하나 이상의 유니코드 스칼라 연속(sequence) 을 말합니다.
let eAcute: Character = "\u{E9}" // é
let combinedEAcute: Character = "\u{65}\u{301}" // e followed by ́
// eAcute is é, combinedEAcute is é
é 는 LATIN SMALL LETTER E WITH ACUTE 혹은 U+00E9 으로 나타낼 수 있는데 e 와 `의 조합으로 만들 수 있다.
extended grapheme cluster 는 많은 복잡한 스크립트 문자를 단일 문자 타입으로 만들 수 있는 방법입니다. 예를 들어, 한글 음절은 합쳐서 사용하거나 분해해서 사용할 수 있습니다. 아래 예시에서 두 상수는 모두 Swift에서 단일 문자 값으로 사용할 수 있습니다.
let precomposed: Character = "\u{D55C}" // 한
let decomposed: Character = "\u{1112}\u{1161}\u{11AB}" // ᄒ, ᅡ, ᆫ
// precomposed is 한, decomposed is 한
extended grapheme cluster 는 다른 유니코드 스칼라를 단일 문자 값의 일부로 묶기 위해 표시된 스칼라를 사용할 수 있습니다.
let enclosedEAcute: Character = "\u{E9}\u{20DD}"
// enclosedEAcute is é⃝
유니코드 스칼라를 쌍으로 결합하여 지역 표시 기호를 단일 문자 값을 만들 수 있습니다. 미국 us 를 예로 들면
let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}"
// regionalIndicatorForUS is 🇺🇸
Counting Characters (문자수 세기)
문자열에서 문자 값의 개수를 검색하려면, 문자열의 count 프로퍼티를 사용합니다.
let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"
print("unusualMenagerie has \(unusualMenagerie.count) characters")
// Prints "unusualMenagerie has 40 characters"
Swift가 문자 값에 extended grapheme cluster를 사용한다는 것은 문자열을 연결하거나 수정하는 것이 문자열의 문자 수에 항상 영향을 미치는 것은 아니라는 것을 의미합니다.
예를 들어, 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
//word 는 cafe` 가 아닌 café 가 된다.
print("the number of characters in \(word) is \(word.count)")
// Prints "the number of characters in café is 4"
// 문자를 추가했음에도 문자열 개수는 그대로 4 이다
extended grapheme cluster 는 여러 유니코드 스칼라로 구성될 수 있습니다. 즉, 다른 문자 (같은 문자에 대한 다른 표현도 포함)를 저장하는 데 서로 다른 양의 메모리가 필요할 수 있습니다. 이 때문에 Swift의 문자는 문자열 표현에서 각각 동일한 양의 메모리를 차지하지 않습니다. 따라서 문자열의 extended grapheme cluster 경계를 결정하기 위해 문자열을 통해 반복하지 않으면 문자열의 문자 수를 계산할 수 없습니다. 특히 긴 문자열 값으로 작업하는 경우 해당 문자열의 문자를 확인하려면 전체 문자열의 유니코드 스칼라에 대해 카운트 속성이 반복되어야 합니다.
count 프로퍼티에서 반환되는 문자 수가 항상 동일한 문자를 포함하는 NSString의 length 프로퍼티와 같지는 않습니다. NSString의 length 는 문자열의 UTF-16 표현에 포함된 16비트 코드 단위 수를 기준으로 하며 문자열 내 유니코드 extended grapheme cluster는 기준으로 하지 않습니다.
Accessing and Modifying a String
매소드나 프로퍼티를 사용해 문자열을 수정할 수 있고, 첨자(subscript) 구문을 사용할 수도 있습니다.
String Indices (문자열 인덱스)
각 문자열 값은 index type, String.Index 과 연관되어 있습니다. String.Index는 문자열안에서 각 각의 문자의 위치에 해당합니다.
위에서 언급한 바와 같이, 문자마다 저장하기 위해 서로 다른 양의 메모리가 필요할 수 있으므로, 어떤 문자가 특정 위치에 있는지 확인하려면 해당 문자열의 시작 또는 끝부터 각 유니코드 스칼라에 대해 반복해야 합니다. 따라서 Swift 문자열은 정수 값으로 인덱싱할 수 없습니다.
startIndex 프로퍼티를 사용해 문자열의 첫번째 문자의 위치에 접근합니다. endIndex 프로퍼티는 문자열의 마지막 문자 다음의 위치를 나타냅니다. 결과적으로 endIndex 프로퍼티는 문자열 첨자에 대한 유효한 인수는 아닙니다. 만약 String이 빈 값이라면 startIndex와 endIndex는 같은 값을 가집니다.
첨자를 사용해 특정 문자열 인덱스에 있는 문자에 접근할 수 있습니다.
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: "")
}
// Prints "G u t e n T a g ! "
Collection 프로토콜을 준수하는 모든 타입에 startIndex, endIndex 프로퍼티와 index(:before), index(after:), index(_:offsetBy:) 메소드를 사용할 수 있습니다. 여기에는 String과 collection 타입으로 잘알려진 Array, Dictrionary, Set이 포함됩니다.
Inserting and Removing (삽입과 제거)
지정된 인덱스의 문자열에 단일 문자를 삽입하려면 insert(_:at:) 메서드를 사용하고, 지정된 인덱스에 다른 문자열의 내용을 삽입하려면 insert(contentsOf:at:) 메서드를 사용합니다.
var welcome = "hello"
welcome.insert("!", at: welcome.endIndex)
// welcome now equals "hello!"
welcome.insert(contentsOf: " there", at: welcome.index(before: welcome.endIndex))
// welcome now equals "hello there!"
지정된 인덱스의 문자열에서 단일 문자를 제거하려면 remove(at:) 메서드를 사용하고, 지정된 범위에서 하위 문자열을 제거하려면 removeSubrange(_:) 메서드를 사용합니다.
welcome.remove(at: welcome.index(before: welcome.endIndex))
// welcome now equals "hello there"
let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex
welcome.removeSubrange(range)
// welcome now equals "hello"
RangeReplaceableCollection 프로토콜을 준수하는 모든 타입에서 insert(_:at:), insert(contentsOf:at:), remove(at:) 및 removeSubrange(_:) 메서드를 사용할 수 있습니다. 여기에는 String과 collection 타입으로 잘알려진 Array, Dictrionary, Set이 포함됩니다.
Substrings (서브스트링)
(서브스트링이라는 단어자체가 어색할 수 있는데 문자열 안에 있는 문자열이라고 생각하면 된다. 다만 문자열(String) 안에 있으므로 문자열이 아니고 substring 이라고 한다. sub를 직역하면 하위이다)
prefix(_:) 같은 메소드를 사용하여 문자열로부터 서브스트링(substring)을 가져올때, 그 결과 값은 Substring의 인스턴스이지 String이 아닙니다. Swift 의 Substring은 대부분의 메소드가 String과 동일합니다. 즉 substring도 문자열과 동일한 방식으로 작업할 수 있습니다. 문자열이 작업하는 시간에 비하면 substring이 훨씬 빠릅니다. 결과를 더 오랫동안 저장하려면 substring을 문자열로 바꿔줘야 합니다.
let greeting = "Hello, world!"
let index = greeting.firstIndex(of: ",") ?? greeting.endIndex
let beginning = greeting[..<index]
// beginning is "Hello"
// Convert the result to a String for long-term storage.
let newString = String(beginning)
문자열과 마찬가지로, 각 서브스트링에는 서브스트링을 구성하는 문자(character)를 저장되는 메모리 영역이 있습니다. 문자열과 서브스트링의 차이점은 성능 최적화로, 서브스트링이 '원래 문자열을 저장하는 데 사용되는 메모리' 혹은 '다른 서브스트링을 저장하는 데 사용되는 메모리' 의 일부를 재사용할 수 있다는 것입니다. (스트링은 유사한 최적화 기능을 갖지만 두 문자열이 메모리를 공유하면 동일합니다.)
이 성능 최적화는 문자열 또는 서브스트링을 수정할 때까지 메모리 복사 성능 비용을 지불할 필요가 없음을 의미합니다. 위에서 언급한 바와 같이 서브스트링은 장기 보관에는 적합하지 않습니다. 원본 문자열을 재사용하기 때문에 서브스트링 중 하나를 사용하는 한 전체 원본 문자열을 메모리에 보관해야 합니다.
위의 예에서 greeting 은 문자열입니다. 즉, 문자열을 구성하는 문자가 저장되는 메모리 영역을 의미합니다. beginning은 greeting의 서브스트링이기 때문에 greeting가 사용하는 메모리를 다시 사용합니다. 이와는 대조적으로 newString은 문자열입니다. 하위 문자열에서 생성된 경우 자체 스토리지가 있습니다. 아래 그림은 이러한 관계를 보여줍니다.
문자열과 서브스트링 모두 StringProtocol 프로토콜을 준수하므로 문자열 조작 함수가 StringProtocol 값을 수락하는 것이 편리합니다. 문자열 또는 서브스트링 값을 사용하여 이러한 함수를 호출할 수 있습니다.
Comparing Strings (문자열 비교)
Swift는 텍스트 값을 비교하는 3가지 방법을 제공합니다.
- String 과 character 가 같은지
- prefix(접두사 = 앞에 붙은 문자) 가 같은지
- suffix(접미사 = 뒤에 붙는 문자) 가 같은지
String and Character Equality (문자열과 문자 동일성)
문자열과 문자가 같은지는 비교연산자에서 설명한 것처럼 == 연산자 와 != 연산자를 사용해서 비교합니다.
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")
}
// Prints "These two strings are considered equal"
두 문자열 값(또는 두 문자 값) 은 extended grapheme clusters 이 규범적(canonically)으로 동일한 경우 동일한 것으로 간주 됩니다. extended grapheme clusters 는 `백그라운드 유니코드 스칼라로 구성된 경우`에도 언어적 의미와 외관이 동일하다면 규범적으로 동일합니다.
(canonically 를 `규범적`으로 해석했는데 정확히는 이해가 안되네요)
예를 들면 é (U+00E9)는 e(U+0065) 와 ` (U+0301)을 합친 것과 규범적으로 같습니다. 이 두 extended grapheme clusters 는 é를 나타내는데 유효한 방법이고 규범적으로 동등하다고 판단됩니다.
// café 의 é를 유니코드 U+0065 로 표현
let eAcuteQuestion = "Voulez-vous un caf\u{E9}?"
// café 의 é를 유니코드 U+0065 + U+0301 로 표현
let combinedEAcuteQuestion = "Voulez-vous un caf\u{65}\u{301}?"
if eAcuteQuestion == combinedEAcuteQuestion {
print("These two strings are considered equal")
}
// Prints "These two strings are considered equal"
반대로 영어 대문자 A 와 러시아 대문자 A 는 같지 않습니다. 보기에는 똑같이 보여도 언어적 의미가 다르기 때문입니다.
let latinCapitalLetterA: Character = "\u{41}"
let cyrillicCapitalLetterA: Character = "\u{0410}"
if latinCapitalLetterA != cyrillicCapitalLetterA {
print("These two characters aren't equivalent.")
}
// Prints "These two characters aren't equivalent."
Swift의 문자열과 문자 비교는 locale-sensitive 하지 않습니다.
Prefix and Suffix Equality (접두사와 접미사가 같은지)
문자열이 특정 문자열을 앞뒤로 가지고 있는지 확인하기 위해 hasPrefix(_:) 와 hasSuffix(_:) 라는 메소드를 사용한다. 두 메소드 모두 String 타입의 단일 인자를 사용하고 Boolean 값을 반환합니다.
아래 예제는 로미오와 줄리엣(셰익스피어) 의 1장 과 2장의 촬영 장소입니다.
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"
]
hasPrefix(_:) 메소드를 사용해 romeoAndJuliet 배열에 접근하여 Act1 장면이 몇 개인지 셀 수 있습니다.
var act1SceneCount = 0
for scene in romeoAndJuliet {
if scene.hasPrefix("Act 1 ") {
act1SceneCount += 1
}
}
print("There are \(act1SceneCount) scenes in Act 1")
// Prints "There are 5 scenes in Act 1"
마찬가지로, hasSuffix(_:) 메소드를 사용하여 Capulet’s mansion 과 Friar Lawrence’s cell 에서 몇 장면이 있는지 알 수 있습니다.
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")
// Prints "6 mansion scenes; 2 cell scenes"
hasPrefix(_:) 및 hasSuffix(_:) 메소드는 각 문자열의 extended grapheme clusters 간에 문자별 표준 동등성을 비교합니다.
Unicode Representations of Strings (유니코드 문자열 표현)
유니코드 문자열이 텍스트 파일 또는 기타 저장소에 기록되면 해당 문자열의 유니코드 스칼라는 `여러 유니코드 정의 인코딩 양식` 중 하나로 인코딩됩니다. 각 형식은 작은 청크(chunks)라는 코드 단위로 문자열을 인코딩합니다. 여기에는 the UTF-8 encoding form(8비트 코드 단위로 인코딩), the UTF-16 encoding form(16비트 코드 단위로 인코딩), the UTF-32 encoding form(32비트 코드 단위로 인코딩)이 포함됩니다.
Swift는 문자열의 유니코드 표현에 액세스하는 여러 가지 다른 방법을 제공합니다. for-in 문을 사용하여 문자열의 개별 문자 값에 유니코드 extended grapheme clusters로 접근할 수 있습니다.
또는 다음 세 가지 유니코드 호환 표현 중 하나로 문자열 값에 액세스합니다.
- UTF-8 코드 단위 모음(문자열의 utf8 속성으로 접근)
- UTF-16 코드 단위 모음(문자열의 utf16 속성으로 접근)
- 문자열의 UTF-32 인코딩 양식과 동일한 21비트 유니코드 스칼라 값의 모음(문자열의 unicodeScalars 프로퍼티로 접근)
각각의 예는 Dog‼🐶 에 대해 다르게 표현합니다.
UTF-8 Representation
string의 utf8 프로퍼티를 반복하여 UTF-8 표현에 접근할 수 있습니다. 이 프로퍼티는 String 타입입니다.
부호없는(unsigned) 8bit 값들의 모음인 UTF8View는 각 비트에 문자열 UTF-8를 표현합니다.
for codeUnit in dogString.utf8 {
print("\(codeUnit) ", terminator: "")
}
print("")
// Prints "68 111 103 226 128 188 240 159 144 182 "
위의 예에서 처음 3개의 십진수 codeUnit 값 (68, 111, 103)은 D, o, g 를 나타내면 UTF-8 표현은 ASCII 표현과 동일합니다. 다음 세 개의 10진수 코드단위 값(226, 128, 188)은 !! 문자의 3바이트 UTF-8 표현입니다. 마지막 4개의 코드단위 값(240, 159, 144, 182)은 🐶 문자의 4바이트 UTF-8 표현입니다.
UTF-16 Representation
string의 utf16 프로퍼티를 반복하여 UTF-16표현에 접근할 수 있습니다. 이 프로퍼티는 String 타입입니다.
부호없는(unsigned) 8bit 값들의 모음인 UTF16View는 각 비트에 문자열 UTF-16를 표현합니다.
for codeUnit in dogString.utf16 {
print("\(codeUnit) ", terminator: "")
}
print("")
// Prints "68 111 103 8252 55357 56374 "
다시 처음 세 개의 codeUnit 값(68, 111, 103)은 D, o , g 문자를 나타냅니다. UTF-16 코드 단위는 문자열의 UTF-8 표현과 동일한 값을 갖습니다 (유니코드 스칼라는 ASCII 문자를 나타내기 때문입니다.)
네 번째 codeUnit 값(8252)은 !! 문자의 유니코드 스칼라 U+203C를 나타내는 16진수 값 203C와 동일한 10진수입니다. 이 문자는 UTF-16에서 단일 코드 단위로 나타낼 수 있습니다.
다섯 번째, 여섯 번째 codeUnit 값(55357 과 56374)은 🐶 문자의 UTF-16 표현입니다. 이 값은 U+D83D(10진수 값 55357)의 high-surrogate 값과 U+DC36(10진수 값 56374)의 low-surrogate 값 입니다.
Unicode Scalar Representation
unicodeScalars 프로퍼티를 반복하여 문자열 값의 유니코드 스칼라 표현에 액세스할 수 있습니다. 이 속성은 UnicodeScalarView 형식으로, UnicodeScalar 타입 값 모음입니다.
각 unicodeScalars에는 UInt32 값 내에 표시되는 스칼라의 21비트 값을 반환하는 값 속성이 있습니다.
for scalar in dogString.unicodeScalars {
print("\(scalar.value) ", terminator: "")
}
print("")
// Prints "68 111 103 8252 128054 "
처음 세 유니코드스칼라 값(68, 111, 103)에 대한 값 속성은 문자 D, o, g를 나타냅니다.
네 번째 codeUnit 값(8252)은 !! 문자의 유니코드 스칼라 U+203C를 나타내는 16진수 값 203C와 동일한 십진수입니다.
다섯 번째 및 최종 유니코드스칼라의 value 타입인 128054는 DOG FACE 문자의 유니코드 스칼라 U+1F436을 나타내는 16진수 값 1F436에 해당하는 십진수입니다.
value 프로퍼티를 접근하는 대신 각 UnicodeScalar 값을 사용하여 문자열 삽입처럼 새 문자열 값을 구성할 수도 있습니다.
for scalar in dogString.unicodeScalars {
print("\(scalar) ")
}
// D
// o
// g
// ‼
// 🐶
3번 째 글 Strings and Characters를 공부해보았습니다.
긴 글 읽어주셔서 감사합니다 😊
'Swift > Swift 공식문서' 카테고리의 다른 글
[Swift] 공식문서 06 - Functions (함수) (0) | 2021.10.11 |
---|---|
[Swift] 공식문서 05 - Control Flow (흐름 제어, 조건문과 반복문) (0) | 2021.10.08 |
[Swift] 공식문서 04 - Collection Types (컬렉션 타입) (0) | 2021.10.06 |
[Swift] 공식문서 02 - Basic Operators (기본 연산자) (0) | 2021.09.09 |
[Swift] 공식문서 01 - The Basics (기본) (0) | 2021.09.08 |
- Total
- Today
- Yesterday
- 책리뷰
- Swift
- swiftUI 기초
- 앱개발
- 부스트캠프iOS
- Combine
- Swift 디자인 패턴
- TODO
- SwiftUI
- Swift DocC
- Swift공식문서
- vapor
- 디자인 패턴
- 개발
- 책
- UX
- 코딩테스트
- 부스트캠프
- 날씨어플
- Swift문법
- todo앱
- 코딩 테스트
- 코딩
- 애플
- 부스트캠프7기
- 프로그래머스
- Swift 서버
- 필독서
- ios
- 책후기
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |