문자열 처리
String 과 StringBuilder, 그리고 보간 문자열입니다.
글자를 다루는 법, 그리고 바꿀 수 없다는 것
string 은 글자를 늘어놓은 것입니다. 이름·주소·입력값처럼
프로그램이 다루는 것의 상당수가 문자열이라, 자르고 붙이고 찾는 일이 자주 생깁니다.
여기서 먼저 알아 둘 것이 하나 있습니다. C#의 문자열은 한번 만들어지면
바뀌지 않습니다. ToUpper() 나
Replace() 는 원본을 고치는 것이 아니라
고쳐진 새 문자열을 만들어 돌려줍니다. 그래서 돌려받은 것을 담아
두지 않으면 아무 일도 일어나지 않은 것처럼 보입니다.
string name = " 홍길동 "; name.Trim(); // 돌려준 것을 버렸습니다 — name 은 그대로 string clean = name.Trim(); // 이렇게 받아야 합니다
이 성질은 안전하지만 값이 비쌉니다. 문자열을 이어 붙일 때마다 새것이 하나씩 만들어지기 때문입니다 — 아래 상세 사용법에서 다시 봅니다.
다듬고 살펴보기
아래 코드는 브라우저 안에서 실제로 실행됩니다. 고쳐서 눌러 보셔도 됩니다.
string raw = " 홍길동 "; string name = raw.Trim(); Console.WriteLine($"[{name}]"); Console.WriteLine(name.Length); Console.WriteLine(name.Contains("길"));
코드는 고쳐서 실행해 볼 수 있습니다. 처음 누를 때만 실행기를 내려받느라 잠시 걸립니다. 적은 코드는 서버로 나가지 않습니다.
앞에 $ 를 붙인 문자열을 보간 문자열이라고
합니다. 중괄호 안에 변수나 식을 그대로 적으면 그 값이 자리에 들어갑니다.
"[" + name + "]" 처럼 이어 붙이는 것보다 읽기 쉬워
지금은 이쪽을 주로 사용합니다.
자주 사용하는 메서드
| 멤버 | 하는 일 | 예시 |
|---|---|---|
| Length | 글자 수(메서드가 아니라 속성입니다) | "abc".Length → 3 |
| Trim | 앞뒤 공백 없애기 | " hi ".Trim() → "hi" |
| ToUpper / ToLower | 대문자 · 소문자로 | "Hi".ToUpper() → "HI" |
| Replace | 찾아서 바꾸기 | "a-b".Replace("-", "/") → "a/b" |
| Split | 기준을 두고 나누어 배열로 | "a,b".Split(',') → { "a", "b" } |
| Substring | 일부만 떼어 내기 | "abcde".Substring(1, 3) → "bcd" |
| Contains | 들어 있는지 묻기 | "abc".Contains("b") → True |
| IndexOf | 몇 번째에 있는지(없으면 -1) | "abc".IndexOf("c") → 2 |
Substring 의 두 번째 값은 끝 자리가 아니라
길이입니다. Substring(1, 3) 은 1번부터 세 글자를
떼어 냅니다. 끝 자리로 읽으면 결과가 한 글자씩 어긋나므로 주의하세요.
비어 있는지 볼 때는 Length == 0 보다
string.IsNullOrEmpty(s) 가 안전합니다. 값이 아예 없는
(null) 경우까지 함께 걸러 주기 때문입니다. 공백만 있는
것도 비어 있는 것으로 보려면
string.IsNullOrWhiteSpace(s) 를 사용합니다.
이어 붙이기가 비싼 까닭
문자열은 바뀌지 않으므로, 이어 붙일 때마다 둘을 합친 새 문자열이
만들어집니다. 몇 번이라면 아무 문제가 없지만 반복문 안에서 수천 번 붙이면
그만큼의 문자열이 만들어졌다 버려집니다. 그럴 때는
StringBuilder 를 사용합니다 — 안에 글자를 쌓아 두었다가
마지막에 한 번만 문자열로 만듭니다.
string s = ""; for (int i = 0; i < 1000; i++) { s += i; } // 문자열이 1000 개 만들어집니다
var sb = new StringBuilder(); for (int i = 0; i < 1000; i++) { sb.Append(i); } string s = sb.ToString();
몇 번 붙이는 정도라면 그냥 이어 붙이세요.
StringBuilder 는 그 자체로 준비하는 값이 있어, 짧은
문자열 서넛을 합치는 자리에서는 오히려 손해입니다. 반복문 안에서 자라날 때만
사용하면 됩니다.
줄바꿈과 역슬래시가 든 문자열
문자열 안에서 \n 은 줄바꿈,
\t 는 탭을 뜻합니다. 그러면 파일 경로처럼 역슬래시가
그대로 필요한 글은 곤란해지는데, 앞에 @ 를 붙이면
적힌 그대로 담깁니다(축자 문자열).
"C:\\temp\\a.txt" // 역슬래시를 두 번씩 적어야 합니다 @"C:\temp\a.txt" // 적힌 그대로 $@"{name}의 경로: C:\temp" // 둘을 함께 사용할 수도 있습니다
C# 11.0부터는 큰따옴표 셋으로 감싸는 원시 문자열도 있습니다. 따옴표나 역슬래시가 많은 글(JSON 등)을 옮겨 적을 때 편합니다.
이 문법, 몇 버전부터 사용할 수 있나요
- 1.0string · StringBuilder · 축자 문자열(@"")
- 6.0보간 문자열 — $"{name}"
- 11.0원시 문자열 — 큰따옴표 셋으로 감싸기
보간 문자열은 C# 6.0(2015)부터입니다. 그 전에는
string.Format("{0}님", name) 처럼 번호를 매겨
적었는데, 값이 여럿이면 번호와 값을 눈으로 맞춰 보아야 했습니다. 오래된
코드에서 이 모양을 만나더라도 잘못된 것이 아니라 그때의 방식입니다.
직접 해보기
string input = " 홍길동 "; 의 앞뒤 공백을 없애고,
홍길동님, 안녕하세요. (3글자) 형태로 출력해보세요.
string csv = "사과,포도,딸기"; 를 쉼표로 나눈 뒤,
각 항목 사이를 · 로 바꾸어 다시 한 줄로 합쳐
출력해보세요.
- 문자열은 바뀌지 않습니다. 다듬은 결과는 받아 두어야 합니다.
- 값을 끼워 넣을 때는 보간 문자열
$"{name}"이 읽기 쉽습니다. Substring의 두 번째 값은 끝 자리가 아니라 길이입니다.- 반복문 안에서 자라나는 문자열은
StringBuilder로 쌓습니다.
C# 버전별 변경 이력 에서 각 버전이 무엇을 더했는지 볼 수 있습니다.