문자열이란?
- 문자(char)의 연속으로 이루어진 자료, 데이터.
- 파이썬에서는 문자열(
str)이 불변(immutable) 객체이므로, 수정 시 새로운 문자열을 생성.
- C 언어에서는
char 배열을 사용하거나 char *를 동적 할당해 사용. (널 문자 \0 로 끝을 표시)
s = "hello"
print(s[1])
문자열의 특징
- 인덱스 접근
s[i]로 개별 문자에 접근 가능 (파이썬: 상수 시간, C: 배열 인덱스 접근)
- 불변성(파이썬)
- 문자열을 직접 수정(
s[2] = 'X') 불가 → 새로운 문자열을 만들어야 함.
- 크기(길이)
- 파이썬:
len(s)로 길이를 쉽게 구함 (O(1)처럼 보이지만 내부 구현에 따라 O(1) 또는 O(n) 가능성).
- C:
strlen(str) 함수로 길이 계산 (실제로 한 문자씩 순회하므로 O(n)).
- 문자열 연산 비용
- 문자열 연결시, 새로 공간을 할당하고 복사 → 길이에 비례한 시간 소요.
요약
| 특징 | 설명 |
|---|
| 문자 배열 | 내부적으로는 문자 하나하나를 인덱스로 구분 |
| 0번 인덱스부터 시작 | s[0]은 첫 글자 |
| 불변(immutable) | 문자열을 직접 수정할 수 없음 |
| 슬라이싱 가능 | 부분 문자열 추출 가능 |
| 많은 내장 함수 지원 | 문자열을 다루기 위한 다양한 기능 제공 |
문자열에서 주로 하는 작업
- 탐색
- 특정 문자가 문자열 안에 존재하는지 찾기.
- 선형 탐색으로 O(N)
- 파이썬 내장:
s.find('a'), 'a' in s 등 (내부적으로도 선형 탐색)
- 슬라이싱 (파이썬)
s[start:end] 형태로 부분 문자열을 구함.
- 실제로는 새 문자열을 생성 (복사가 발생) → O(N)
s = "hello"
print(s[1:4])
print(s[:2])
print(s[2:])
- 변환/조작
s.replace(old, new): 부분 문자열을 다른 문자열로 교체 (새로운 문자열 리턴)
s.split(delim): 구분자로 나누어 리스트 형태로 반환
s.strip(): 공백이나 특정 문자 제거
- 문자열 뒤집기
- 파이썬:
s[::-1] (슬라이싱 응용)
- 직접 구현 시, O(N)의 시간에 두 인덱스를 바꿔가며 스왑.
인덱스 접근
s = "hello"
print(s[0])
print(s[-1])
직접 구현 예시 (파이썬, 내장함수 최소화)
문자열 뒤집기
def reverse_string(st):
reversed_str = ""
for i in range(len(st)-1, -1, -1):
reversed_str += st[i]
return reversed_str
s = "Hello"
print(reverse_string(s))
문자열 선형 탐색
def find_char(st, ch):
"""st에서 문자 ch를 찾으면 인덱스 반환, 없으면 -1"""
for i in range(len(st)):
if st[i] == ch:
return i
return -1
print(find_char("Hello", 'l'))
print(find_char("Hello", 'z'))
부분 문자열(substring) 확인
def is_substring(main_str, sub_str):
"""main_str에 sub_str이 포함되어 있는지 확인"""
M = len(main_str)
S = len(sub_str)
for i in range(M - S + 1):
match = True
for j in range(S):
if main_str[i+j] != sub_str[j]:
match = False
break
if match:
return True
return False
print(is_substring("Hello World", "World"))
print(is_substring("Hello World", "Bye"))
문자열 관련 파이썬 내장 함수 정리
| 함수 | 설명 | 예시 | C언어 대체 방식 |
|---|
len(s) | 문자열 길이 | len("hello") → 5 | strlen() 함수 사용 또는 직접 카운트 |
s.upper() | 대문자로 변환 | "abc".upper() → "ABC" | 반복문 + toupper() |
s.lower() | 소문자로 변환 | "ABC".lower() → "abc" | 반복문 + tolower() |
s.strip() | 앞뒤 공백 제거 | " hi ".strip() → "hi" | 반복문으로 공백 체크 |
s.lstrip() | 왼쪽 공백 제거 | " hi".lstrip() → "hi" | - |
s.rstrip() | 오른쪽 공백 제거 | "hi ".rstrip() → "hi" | - |
s.split() | 문자열 나누기 | "a,b,c".split(',') → ['a','b','c'] | 직접 파싱 (for + 조건문) |
s.find(sub) | 부분 문자열 위치 | "abcde".find("cd") → 2 | 직접 구현 (위 예시 참고) |
s.replace(a, b) | 문자열 치환 | "aabb".replace("a","c") → "ccbb" | 직접 구현 필요 |
s.isdigit() | 숫자 여부 확인 | "123".isdigit() → True | 문자 하나하나 확인 |
split() 함수
text = "apple,banana,grape"
result = text.split(',')
print(result)
- 기본 동작:
split(separator)
separator로 문자열을 나눠서 리스트 형태로 반환
- 생략하면 공백 기준으로 나눔 →
text.split()
- C언어에서는 문자열 순회하며 구분자를 기준으로 직접 나눠야 함
strip() 함수
s = " hello "
print(s.strip())
print(s.lstrip())
print(s.rstrip())
- 문자열 앞뒤의 공백 문자(또는 지정 문자)를 제거
- 내부적으로 문자 하나하나 비교해서 제거
- C언어에서는 수동으로 인덱스 조정하면서 공백 건너뛰어야 함
문자열 불변(Immutable)의 의미
s = "hello"
s[0] = 'H'
s = 'H' + s[1:]
print(s)
- 파이썬의 문자열은 값을 바꾸는 게 아니라, 새로 만드는 방식으로 동작
- 메모리 관점에서 비효율이 될 수 있음 (C에서는 직접 바꾸는 것이 가능)
정리
| 핵심 포인트 | 설명 |
|---|
| 문자열은 불변이다 | 수정이 아닌 새 문자열을 생성 |
| 파이썬은 많은 내장 함수를 제공 | split, strip, replace 등 |
| 내장함수 없이 구현도 가능해야 함 | C언어에서는 전부 직접 만들어야 하기 때문 |
| 슬라이싱은 강력한 기능 | s[1:4], s[::-1] 등 |
추가 tip
- 문자열은 배열처럼 인덱스로 처리
- 파이썬에서는
str, C언어에서는 char[]로 다룸
- 내장함수에 익숙해지되, 함수 없이도 구현하는 습관을 들이기
- C언어에서는 문자열 처리할 때 *널문자
\0로 종료를 표시함
C 언어에서의 문자열과 차이
- *널 문자(
\0)**로 문자열의 끝을 표시해야 함.
strlen(), strcpy(), strcat() 등 표준 라이브러리 함수를 사용하거나 직접 구현.
- 수정 가능(배열이므로), 단 ‘버퍼 크기 초과’에 유의해야 함.
예: char str[10] = "Hello"; 라면, 내부적으로 'H' 'e' 'l' 'l' 'o' '\0' ... 형태로 저장.