흰둥이는 코드를 짤 때 짖어 (왈!왈!왈!왈!왈!왈!왈!왈!왈!왈!왈!)

(파이썬, 시험) 전화번호부 만들기 본문

시험

(파이썬, 시험) 전화번호부 만들기

흰둥아솜사탕 2023. 3. 17. 15:30
728x90
반응형

 

 

 

- class 선언

# 전화번호 목록에 접근할 때 사용되는 클래스입니다.
class PhoneBook:

  # 객체를 불러올 때 전화번호부를 메모리에 리스트로 담는 생성자 -----------------------------
  def __init__(self):
    self.target_path = './phone_book.txt'
    self.user_list = []

    # 파일을 불러올 때 만약 파일이 없다면 예외처리로 잡아냅니다.
    try:
      file = open(self.target_path, 'r')
      tump_data = file.read()
      # 혹시라도 파일안에 내용이 없는 상태로 저장되었는지 검사합니다.
      if tump_data != '':
        tump_list = tump_data.split('\n') # 먼저 정보를 각각 유저마다의 데이터를 나눠서 리스트에 담습니다.
        
        # 유저가 가지고 있는 데이터들을 나눠서 리스트에 담습니다.
        for tump_data in tump_list:
          user_data = tump_data.split('/')
          self.user_list.append(user_data)

    # 파일이 없을 경우 내용이 안들어있는 파일을 생성합니다.
    except:
      file = open(self.target_path, 'w')
      file.write('')

    finally:
      file.close()

  # user_list(메모리에 있는 리스트)에 유저 정보를 추가 ---------------------------------------
  def insert(self, content_list):

    # 먼저 user_list에 값이 존재하는지 검사합니다.
    if len(self.user_list) != 0:

      # user_list에 유저 정보중 전화번호들을 추가하려는 유저 정보의 전화번호와 비교해 중복 검사를 합니다.
      for user_data in self.user_list:
        if user_data[1] == content_list[1]:
          return False  # 중복할 경우 리스트에 담기전에 메소드를 종료시키며 False를 return합니다.
    
    # 조건에 걸리지 않을 경우 user_list에 추가한 후 오름차순으로 정렬한 후 True를 return합니다.
    self.user_list.append(content_list)
    self.user_list.sort() # 정렬 할 때 담겨있는 리스트중 가장 앞에있는 '이름'부터 정렬하게 됩니다.
    return True

  # user_list를 출력 ------------------------------------------------------------------------
  def showAll(self):
    # 데이터가 있는지 검사하는 용도입니다.
    flag = False

    # user_list에 있는 데이터들을 출력하며 데이터가 없을 시 for문을 돌지 않아 flag값을 바꿀 수 없게 됩니다. 
    for user_data in self.user_list:
      print(user_data)
      flag = True
    
    # flag로 데이터가 있는지 검사하여 결과에 따라 return값이 다르게 반환해줍니다.
    return '\n' if flag else '아직 정보가 없습니다.'

  # user_list에서 검색하여 출력 -------------------------------------------------------------
  def show(self, show_select, content):
    # 데이터가 있는지 검사하는 용도입니다.
    flag = False
    # 선택한 검색 카테고리를 인덱스 값으로 이용하기 위해 -1을 연산 해줍니다.
    select = show_select - 1

    # 만약 검색 카테고리가 전화번호일 경우입니다.
    if select == 1:
      for user_data in self.user_list:
        # 유저가 가지고 있는 전화번호에 검색어가 포함되어 있으면 출력해줍니다.
        if user_data[select].count(content) != 0:
          print(user_data)
          flag = True

    # 전화번호를 제외한 다른 검색 카테고리일 경우입니다.
    else:
      for user_data in self.user_list:
        # 검색어가 정확히 유저 데이터와 일치할 경우에만 출력해줍니다.
        if user_data[select] == content:
          print(user_data)
          flag = True
    
    # flag로 데이터가 있는지 검사하여 결과에 따라 return값이 다르게 반환해줍니다.
    return '\n' if flag else '찾으시는 정보가 없습니다.'

  # user_list에서 해당 전화번호를 삭제 ------------------------------------------------------
  def delete(self, phone_num):

    # 삭제할 경우 해당 데이터의 인덱스 값이 필요하여 range를 이용하였습니다.
    for i in range(0, len(self.user_list)):

      # 입력한 전화번호와 완벽히 일치하는 유저의 정보를 user_list에서 삭제합니다.
      if self.user_list[i][1] == phone_num:
        del self.user_list[i]
        return '삭제가 완료 되었습니다.'

    # 입력한 전화번호가 존재하지 않을 경우입니다.
    return '삭제할 번호가 존재하지 않습니다.'

  # user_list를 파일에 업로드 ---------------------------------------------------------------
  def save(self):

    # 파일을 새롭게 덮어 씌우기 위해 w를 이용하였습니다.
    with open(self.target_path, 'w') as f:
      text = ''
      for user_data in self.user_list:
        # 유저의 정보를 '/'단위로 구분하기위해 join()을 사용했습니다.
        text += '/'.join(content for content in user_data)
        # 유저의 단위는 '\n'단위로 구분하였습니다.
        text += '\n'

      # 마지막에 오는 데이터'\n'을 삭제 시켜주며 만약 데이터가 아무것도 없다면 삭제를 생략합니다.
      if text != '':
        text = text[:-1]
      
      f.write(text)
    return '저장이 완료되었습니다.'

- 동작

# 객체를 선언해줍니다.
pb = PhoneBook()

# 프로그램이 정상 종료시 까지 무한 반복을 해주기 위해 while문을 사용하였습니다.
while True:
    print('\n1. 연락처 입력\n2. 연락처 목록\n3. 연락처 검색\n4. 연락처 삭제\n5. 전화번호부 저장\n6. 프로그램 종료')
    
    # 사용자가 번호입력을 잘못된 타입이나 범위 밖의 값으로 입력하는 것을 방지하기 위한 예외 처리입니다.
    try:
      select = int(input('번호를 선택하세요: '))

      # 번호 범위를 벗어날 경우 에러를 발생 시킵니다.
      if select < 1 or select > 6:
        raise Exception()
    except:
      print('잘못 입력하셨습니다.')
      continue # 예외가 발생시 while문을 재실행 시켜줍니다.

    if select == 1: # ------------------------------------------------------------------------

      # 추가할 유저 정보를 list에 담습니다.
      content_list = []
      content_list.append(input('이름을 입력하세요: '))
      content_list.append(input('전화번호를 입력하세요: '))
      content_list.append(input('주소를 입력하세요: '))
      content_list.append(input('이메일을 입력하세요: '))
      content_list.append(input('그룹을 입력하세요: '))

      # PhoneBook클래스에 insert()메소드를 이용하여 데이터를 user_list에 추가합니다.
      # insert()메소드는 전화번호 유효성 검사를 하여 bool타입으로 return해줍니다.
      if pb.insert(content_list):
        print('입력이 완료 되었습니다.')
      else:
        print('존재하는 전화 번호입니다.')

    elif select == 2: # ----------------------------------------------------------------------
      # showAll()은 모든 목록을 불러오는 메소드 입니다.
      print(pb.showAll())

    elif select == 3: # ----------------------------------------------------------------------
      # 검색 카테고리를 정할시 잘못 입력하면 다시 입력 받기위해 반복문을 이용하였습니다.
      while True:
        print('\n1. 이름으로 검색\n2. 전화번호로 검색\n3. 주소로 검색\n4. 이메일로 검색\n5. 그룹으로 검색')

        # 사용자가 번호입력을 잘못된 타입이나 범위 밖의 값으로 입력하는 것을 방지하기 위한 예외 처리입니다.
        try:
          show_select = int(input('번호를 선택하세요: '))
          # 번호 범위를 벗어날 경우 에러를 발생 시킵니다.
          if show_select < 1 or show_select > 5:
            raise Exception()
        except:
          print('잘못 입력하셨습니다.')
          continue

        content = input('검색어를 입력해주세요: ')

        # show()는 검색에 해당하는 데이터만 출력해주는 메소드입니다.
        print(pb.show(show_select, content))
        break

    elif select == 4: # ---------------------------------------------------------------------
      phone_num = input('삭제할 전화번호를 입력하세요: ')

      # delete()는 해당 전화번호를 가지고 있는 유저를 삭제하는 메소드입니다.
      print(pb.delete(phone_num))

    elif select == 5: # ----------------------------------------------------------------------
      # save()는 user_list를 파일에 업로드하는 메소드 입니다.
      print(pb.save())

    elif select == 6: # ----------------------------------------------------------------------
      # break로 while문을 멈추며 프로그램을 종료 시킵니다.
      print('프로그램을 종료합니다.')
      break

 

이후 느낀점

클래스 선언에 관해서 좀 부족했던거 같다.

target_path 를 생성자에서 선언 하는것이 아닌 매개변수로 target_path를 받아서 선언하는 것이 객체를 선언 할때마다 다른 텍스트 파일 경로를 만들 수 있기 때문에 알맞은 객체 지향프로그래밍이 아니였나 아쉬움이 남는다.

 

그리고 유저 정보를 담는 1번 선택지를 좀더 사용자가 편하도록 중간에 취소할 수 있는 버튼이나 돌아가기 버튼을 구현 했다면 좋았을거 같다.

728x90
반응형
Comments