[Swift] Strings and Characters

상 원·2022년 7월 3일
0

Swift

목록 보기
7/31
post-thumbnail
post-custom-banner

swift의 String은 Foundation의 NSString과 연결되어 있기 때문에, Foundation을 import하면 NSString의 함수를 String에도 쓸 수 있다.

String

문장 여러 줄에 걸쳐 쓰기

let str = """
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 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."
"""

Extended String Delimiters

\n 같은 명령어로 문자열에 특수효과(?)를 집어넣은 문자열을 #로 감싸서 다 무력화해버릴 수 있다.

let str = #"""
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 str = #"""
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 str1 = ""
let str2 = String()
//str1, str2 모두 빈 문자열이 됨.
if str2.isEmpty{
	//str2가 빈 문자열인지 체크할 수 있음
}

문자열은 값 타입(Value Type)!!

타입에는 두 가지가 존재하는데, Value type과 Reference type, 요 두 가지가 있다!
쉽게 말해 value type은 값이 변경되지 않고 복사되어 참조되는 것, reference type은 값이 복사되어 참조되는 것이 아니라 그 자체가 참조되는 것이다.
그니까 value type은 원본이 변경되지 않고, reference type은 원본이 변경되는 거라고 생각하면 편할듯.

새로운 String을 만들면, 이 값은 함수나 메소드에 전달되거나 변수/상수에 assign될 때 복사되어 전달된다.

Swift의 copy-by-default String성질은 함수나 메소드가 문자열을 넘겨줄 때, 이 문자열의 원본은 변경되지 않기 때문에 편하게 사용할 수 있도록 해 준다.

Value type과 Reference type은 다음에 더 자세히 다뤄보도록 합시당.

문자 갯수 세기

문자열이 몇 개의 문자로 이뤄졌는지 확인하려면, count 속성을 사용하면 된다.

let str = "This is test string."
print(str.count)
//20

문자열 접근과 변경하기

문자열 인덱스 접근하기

Swift의 문자는 각각 다른 양의 메모리를 먹기 때문에, 문자열에서 정수값의 인덱스로 문자를 나타낼 수가 없다. 그래서 다음과 같은 문법을 사용할 수밖에 없음.

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, 해당 인덱스에서 offsetBy만큼 떨어진 인덱스

//존재하지 않는 인덱스에 대한 접근은 런타임 에러 발생
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 ! " 출력됨

Inserting and Removing

문자열에 문자 하나 또는 문자열을 삽입하는 것은 다음과 같이 할 수 있다.

// 문자 하나 삽입하기, insert(_: at:) 사용
var welcome = "hello"
welcome.insert("!", at: welcome.endIndex)
// welcome now equals "hello!"

// 문자열 삽입하기, insert(contentsOf: at:) 사용
welcome.insert(contentsOf: " there", at: welcome.index(before: welcome.endIndex))
// welcome now equals "hello there!"

문자열에서 문자 하나 또는 문자열을 제거하는 것은 다음과 같이 할 수 있음.

// 문자 하나 제거하기, remove(at:) 사용
welcome.remove(at: welcome.index(before: welcome.endIndex))
// welcome now equals "hello there"

//문자 범위로 제거하기, removeSubrange(_:) 사용
let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex
welcome.removeSubrange(range)
// welcome now equals "hello"

insert(_: at:), insert(contentsOf: at:), remove(at:), removeSubrange(_:)는 RangeReplaceableCollection 프로토콜을 따르는 모든 타입에 적용될 수 있다. 따라서 Array, Dictionary, Set에 적용될 수 있다.

Substrings

문자열에서 prefix( _: ) 같은 함수를 써서 얻은 substring의 경우에는 Substring 인스턴스가 만들어진다. 또다른 String이 만들어지는 게 아님.
이 Substring의 경우에는 String에 쓸 수 있는 걸 거의 다 쓸 수 있지만, 이걸 긴 시간 동안 쓸 수가 없다는 차이점이 있다.
긴 시간동안 쓰고 싶다면 String 인스턴스로 변환해 줘야 한다.

이 Substring도 String처럼 메모리공간을 점유하고 있는데, 차이점은 이놈은 기존의 문자열이나 다른 Substring 문자열의 메모리 일부분을 참조해 재사용한다는 것이다.

그래서 이 Substring을 사용하려면 원본 String도 메모리에 계속 존재해야 하는데, 만약 이 원본 문자열을 사용하지 않아도 이 Substring때문에 남아 있어야 하는 일이 생긴다. 메모리가 낭비돼버림!
그래서 이 Substring을 오래 쓰고 싶으면 String 인스턴스로 만들어서 사용하고자 하는 문자만 메모리에 올려놓고 쓰는 것이 좋다.

let greeting = "Hello, world!"
let index = greeting.firstIndex(of: ",") ?? greeting.endIndex
let beginning = greeting[..<index]
// beginning is "Hello"

// 긴 시간동안 사용하기 위해 String으로 변환해줌
let newString = String(beginning)

Prefix and Suffix equality

Prefix는 접두사, 즉 문자열 앞쪽에 붙는 단어이다.
Suffix는 반대로 접미사, 즉 문자열 뒤쪽에 붙는 단어임.
그래서 문자열 비교 시 이 속성들을 사용할 수 있다.

//로미오 앤 줄리엣의 대본임
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"
]

//Act 1의 접두사를 가진 문자열의 갯수를 세려고 함
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"

//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"
profile
ios developer
post-custom-banner

0개의 댓글