알고리즘

String

Disciple428 2024. 2. 5. 20:03
  • 컴퓨터에서의 문자 표현

각 문자에 대응하는 숫자를 정해 놓고 이것을 메모리에 저장한다.

영어가 대소문자를 합치면 52자이므로 6(2**5 = 64)비트면 모두 표현할 수 있다.

이를 코드 체계라고 한다.

ex) 000000 → a , 000001 → b

 

네트워크가 발전하기 전에는 각 지역 별로 코드 체계가 달랐으나 이후 서로 정보를 주고 받을 때

정보를 다르게 해석하는 문제가 발생 → 표준안이 만들어지게 됨. (ASCII)

아스키 코드!

→ 확장 아스키는 표준 문자 이외에 악센트 문자, 도형 문자, 특수 문자, 특수 기호 등 부가적인 문자를 128개 추가하였다. 그러나 표준 아스키와 달리 서로 다른 프로그램이나 컴퓨터 사이에서 교환되지 못한다. 확장 아스키는 프로그램이나 컴퓨터 또는 프린터가 그것을 해독할 수 있도록 설계되어 있어야 올바로 해독할 수 있다.

→ 오늘날 대부분 컴퓨터는 문자를 읽고 쓰는데에 아스키 형식을 사용한다. 그런데 컴퓨터가 발전하면서 각 나라에서도 자국의 문자를 표현하기 위해 코드 체계를 만들어 사용하게 됨.

우리나라도 한글 코드 체계를 만들어 사용했고 조합형, 완성형 두 종류를 가지고 있었다.

그래서 국가 간 정보를 교환할 때 자국의 코드 체계를 타 국가가 가지고 있지 않으면 정보를 잘못 해석하는 문제가 생겼다. 그래서 다국어 처리를 위해 표준을 마련하는데, 이것이 유니코드 이다.

EX) B30 + 0 = 대 , 003 + 0 = 0

 

  • 유니코드도 다시 characeter set으로 분류됨.

→ UCS-2, UCS-4 / 유니코드에 적당한 외부 인코딩이 필요함.

 

  • 문자열

fixed length / variable length

variable length → length controlled / delimited

자바의 문자열은 length controlled , c언어의 문자열은 delimited 이다.

자바에서는 문자열 클래스에서 기본적인 객체 메타 데이터 외에 해시 값, 문자열의 길이, 문자열 데이터의 시작점, 실제 문자열 배열에 대한 value 등을 메모리에 저장하고 있다.

c언어는 문자열의 길이 값을 따로 저장하고 있지 않기 때문에 길이를 물어보면 일일이 세서 알려준다.

 

  • 참고

list ( input() ) = [’a’ , ‘b’ , ‘c’] → 가변 가능한 데이터! (리스트 안 요소 일부를 바꿀 수 있다)

input() = ‘abc’ → 불가변한 데이터! (문자열 내 일부를 수정할 수 없다)

하지만 둘 다 인덱스로 접근 가능하다.

 

  • strlen() 함수 만들어 보기

while a[i] ≠ \0

count += 1

i += 1

 

  • 자바에서의 문자열 처리

문자열 데이터를 저장, 처리해주는 클래스를 제공한다.

string 클래스를 사용

 

  • 파이썬에서의 문자열 처리

char 타입이 없다.

문자열 기호로 ‘, “ , ‘’’, “”” 을 사용

‘+’ → 문자열 연결

‘*’ → 문자열 반복

문자열은 시퀀스 자료형으로 분류되어 인덱싱, 슬라이싱 연산을 사용할 수 있다.

튜플과 마찬가지로 요소값을 변경할 수 없다!

 

  • c와 자바의 string 처리의 기본적인 차이점

c는 아스키 코드로 저장

자바는 유니코드(UTF16, 2byte)로 저장

파이썬은 유니코드(UTF8)로 저장

문자열 길이를 출력하면 c는 바이트 수를, 자바와 파이썬은 눈으로 보이는 문자열 길이를 출력한다.

 

  • 문자열 뒤집기

자기 문자열에서 뒤집는 방법이 있고 새로운 빈 문자열을 만들어서 타켓으로 쓰는 방법이 있다.

자기 문자열을 이용할 경우에는 swap을 위한 임시 변수가 필요하고 반복 수행을 문자열 길이의 절반만 수행해야 한다! (전부 다 해버리면 다시 원상태로 돌아와버린다)

 

  • 파이썬에서 문자열 뒤집기

[::-1] 을 사용

또는 list 로 변환 후 .reverse() 로 뒤집고 이후 ‘’.join() 로 다시 문자열로 만들기

아니면 for 문과 인덱스 연산을 사용해서 뒤집을 수도 있다.

c언어는 strcmp() 함수

자바는 equals() 메소드를 제공

(문자열 비교에서 == 연산은 메모리 참조가 같은 지 묻는 것이다)

파이썬에서는 == 연산자와 is 연산자를 제공한다.

( == 연산자는 내부적으로 특수 메서드 eq() 를 호출)

s1 = 'abc'
s2 = 'abc'
print(s1 == s2)
print(s1 is s2)

s3 = s1[:2] + 'c'
print(s1 == s3)
print(s1 is s3)
print(s3)

== → 내용이 같니?

is → 메모리 주소가 같니?

 

  • 문자열 비교

c코드에서 문자열 비교함수를 만들기

문자열이 같으면 0을 반환

str1이 str2보다 사전 순서상 앞서면 음수 혹은 -1 반환

str1이 str2보다 사전 순서상 나중이면 양수 혹은 1 반환

 

  • 문자열 숫자를 정수로 변환하기

c 언어에서는 atoi() 함수를 지공한다. 역함수로는 itoa()가 있다.

자바에서는 숫자 클래스의 parse 메소드를 제공

(역함수로는 tostring() 메소드를 제공한다)

파이썬에서는 숫자와 문자변환 함수를 제공한다.

ex) int, float, str, repr 등

 

  • str() 함수를 사용하지 않고, itoa() 를 구현해 보기
def itoa(a):
    s = ''
    while a>0:
        s = chr(a%10 + ord('0')) + s
        a // 10
        return s

ans = itoa(123)     ans = '123'
print(ans)

  • 문자열 뒤집기 (보충)

문자열이 수정이 불가능하기 때문에 내부적으로는 [::-1] 이 가능

또는

반복 수행하여 문자열을 하나씩 읽어서 바꿀 수 있는데, 바꾸는 반복 수는 문자열 길이가 홀수일 경우엔 가운데 남는 문자가 하나 생기기 때문에 문자열 길이를 2로 나눈 몫으로 한다.

그리고 이때 역시 문자열은 불가변하기 때문에 타입을 리스트로 변환하고 진행한다.

arr = 'algorithm'
arr = list(arr)
N = len(arr)   # 반복 횟수 = N // 2
for i in range(N//2):
    arr[i], arr[N-1-i] = arr[N-1-i], arr[i]

print(''.join(arr))
  • 회문 판단하기
arr = input()
N = len(arr)

isPalindrome = True
for i in range(N//2):   # 절반으로 쪼개서 다 교환한 후에 비교할 필요 없이
    if arr[i] != arr[N-1-i]:    # 절반으로 나눠서 비교한 것이 다 같으면 회문이라고 판단가능
        isPalindrome = False    # 중간에 다른거 발견하면 더 비교할 것 없이 반복 빠져나온다
        break                   # 다 뒤집지 않고도 회문을 판별할 수 있다

문자열은 읽기용으로만 쓰면 리스트처럼 접근할 수 있다.

똑같이 인덱스를 사용할 수 있기 때문에!

  • str() 함수를 사용하지 않고, itoa() 를 구현하기 (보충)
# ord(문자) -> 문자의 코드 값 반환
# chr(코드값) -> 코드 값에 대응하는 문자를 반환
# 0 ~ 9 문자들의 코드 값은 1씩 증가하는 값들이다. 일부러 이렇게 구현해놓음!
# ord('0') + num  -> num에 저장된 숫자의 문자 코드 값이 나옴!
# chr(ord('0') + num) -> 다시 문자로 변환 가능
def itoa(num):
    result = ''
    while num > 0:
        digit = num % 10
        result = chr(ord('0') + digit) + result 
# 숫자 순서를 지키기 위해 result 앞에 붙여가면서 진행
        num //= 10
    return result

result = itoa(12345)
print(result, type(result))  # '12345'
  • 리스트 안에 있는 1의 자리 숫자를 하나씩 가져와서 여러 자리 수 만들기
arr = [3, 2, 1, 0, 7]
num = 0
for val in arr:
    num = num * 10 + val

print(num)  # 32107