1. 개요 & 알고리즘

단순 연결 리스트를 이용하면 작은 데이터베이스를 구축할 수 있습니다. 여기서는 데이터베이스까지는 아니지만 명함을 입력하고, 삭제하고, 검색하고, 리스팅하고, 디스크에 저장하고, 디스크에서 읽어들이는 등의 기능을 가진 간단한 프로그램을 작성해 봅니다. ("C로 배우는 알고리즘"[각주:1]) - 프린트 출력 기능은 제외하였다.


1. 저장 필드로 이름, 회사, 전화번호만 갖는다.

2. 메뉴는 다음과 같다.

   2.1. 명합을 입력 받는다.

   2.2. 이름으로 찾아서 명함을 삭제한다

   2.3. 이름으로 명함을 검색한다.

   2.4. 디스크에서 명함을 읽는다.

   2.5. 디스크에 명함을 저장한다.

   2.6. 명함들의 리스트를 화면에 보여준다.

   2.7. 프로그램을 끝낸다.


2. 동작 코드

기본적인 Node의 정의는 다음과 같습니다.

class NameCardNode:
def __init__(self, name, corp, tel):
self.name = name
self.corp = corp
self.tel = tel
self.next = -1


실제 함수들을 포함하는 NameCardList classs의 초기화는 다음과 같습니다.

class NameCardList:
def __init__ (self):
self.head = NameCardNode("", "", -1)
self.tail = NameCardNode("", "", -1)
self.head .next = self.tail
self.tail.next = self.tail

inputCard(name, corp, tel), deleteCard(name), deleteNodeAll(), searchCard(name), printCard(), printCardAll()함수들도 작성했습니다.


노드들을 파일로 저장하는 함수는 다음과 같이 작성했습니다.

def saveCard(self, fileName):
fd = open(fileName, 'wb')
t = self.head.next
while t != self.tail:
# Use pickle to save "object" itself
pickle.dump(t.name, fd)
pickle.dump(t.corp, fd)
pickle.dump(t.tel, fd)
t = t.next
fd.close()

파일로부터 노드를 다시 읽어오는 함수는 다음과 같이 작성했습니다.

def loadCard(self, fileName):
try:
fd = open(fileName, 'rb')
except FileNotFoundError:
print("Error : \"%s\" file can't be found" % fileName)
return False

while True:
# Use pickle to load "object" itself
try:
name = pickle.load(fd)
corp = pickle.load(fd)
tel = pickle.load(fd)
self.inputCard(name, corp, tel)
except EOFError:
break
fd.close()
return True

마지막으로, 간단한 CLI(Command Line Interface) 명령을 수행하기 위한 메뉴는 selectMenu()로 다음과 같이 작성했습니다.

def selectMenu():
print("")
print("Namecard Manager")
print("-------------------------------------")
print("1. Input Namecard")
print("2. Delete Namecard")
print("3. Search Namecard")
print("4. Load Namecard")
print("5. Save Namecard")
print("6. List Namecard")
print("7. End Program")
while(True):
print("")
# Try to handle only integer
try:
i = int(input("Select operation -> "), 10)
except ValueError:
pass
else:
if i > 0 and i < 8:
break
return i


3. 실행 코드

selectMenu() 함수를 호출해서 명령을 입력 받는 실행 코드는 아래와 같이 작성했습니다. ("C로 배우는 알고리즘" 리스트 3-7 : NAMECARD.C에 대응)

# main() function
if __name__ == "__main__":
fileName = "Namecard.dat"
# Initialize namecard class
nameCard = NameCardList()
while(True):
menuNum = selectMenu()
# End program
if menuNum == 7:
break

# Input namecard
if menuNum == 1:
print("Input namecard menu : ")
name = input(" Input name : ")
corp = input(" Input corporation : ")
tel = input(" Input telephone number : ")
if name == "":
print("Name in mandatory. Please input name.")
continue
else:
nameCard.inputCard(name, corp, tel)

# Delete namecard
elif menuNum == 2:
name = input("Input name to delete ->")
results = nameCard.deleteCard(name)
if results is None:
print("Can't find that name.")

# Search namecard
elif menuNum == 3:
name = input("Input name to search ->")
results = nameCard.searchCard(name)
if results is None:
print("Can't find that name.")
else:
nameCard.printCard(results)

# Load namecard
elif menuNum == 4:
if nameCard.loadCard(fileName) == True:
print("Load namecard done!!")

# Save namecard
elif menuNum == 5:
nameCard.saveCard(fileName)
print("Save namecard done!!")

# List namecard
elif menuNum == 6:
nameCard.printCardAll()

4. Tips

1. saveCard()를 사용해서 파일에 데이터를 저장하거나, loadCard()를 사용해서 파일에서 데이터를 로드할 때, Python이 제공하는 pickle 모듈을 사용했습니다. 위 예제에서와 같이 각각 pickle.dump()와 pickle.load()를 사용해서 매우 손쉽게 처리할 수 있었습니다.([각주:2]), ([각주:3]), ()

2. 실제 코드를 보면,  try ~ else 형식의 예외 처리 방법[각주:4]이 정리되어 있습니다. Integer로 입력을 받을 때등등에 예외 처리를 추가했습니다. 가장 기본적인것에 대해서, 시험을 하면서 발생한 경우에 대해서만 추가했습니다.

예를 들면, while() 내에서 데이터를 load 하는 pickle.load()를 계속 실행하는 경우, save된 데이터를 모두 읽고 나서 아래와 같은 에러가 발생했습니다. 이때 EOFError에 대해서 예외 처리 코드(try...except...)를 추가하면 동작했습니다.

    name = pickle.load(fd)
EOFError: Ran out of input


5. 코드

https://github.com/steady08/python_beginner_algorithm/blob/master/Chapter_03/Ch_03_7.py


  1. http://www.yes24.com/24/goods/18003 [본문으로]
  2. http://agfree.cafe24.com/?p=909 [본문으로]
  3. https://codeonweb.com/entry/9e4455b5-175c-480c-b346-8c7bf3f52a2e [본문으로]
  4. https://wikidocs.net/30 [본문으로]
반응형

+ Recent posts