##############################################################################
# Parte do livro Introdução à Programação com Python
# Autor: Nilo Ney Coutinho Menezes
# Editora Novatec (c) 2010-2017
# Primeira edição - Novembro/2010 - ISBN 978-85-7522-250-8
# Primeira reimpressão - Outubro/2011
# Segunda reimpressão - Novembro/2012
# Terceira reimpressão - Agosto/2013
# Segunda edição - Junho/2014 - ISBN 978-85-7522-408-3
# Primeira reimpressão - Segunda edição - Maio/2015
# Segunda reimpressão - Segunda edição - Janeiro/2016
# Terceira reimpressão - Segunda edição - Junho/2016
# Quarta reimpressão - Segunda edição - Março/2017
# Terceira Edição - Janeiro/2019
#
# Site: http://python.nilo.pro.br/
#
# Arquivo: exercicios\capitulo 09\exercicio-09-28.py
##############################################################################
# Como o formato do arquivo se torna cada vez mais complicado,
# vamos usar o módulo pickle do Python para gravar e ler a agenda.
#
# Desafio extra:
# Modifique o programa para exibir um submenu de gerência de telefones.
# Este sub menu seria exibido na hora de adicionar e alterar telefones.
# Operações: adicionar novo telefone, apagar telefone, alterar telefone
import pickle
agenda = []
# Variável para marcar uma alteração na agenda
alterada = False
tipos_de_telefone = [ "celular" , "fixo", "residência", "trabalho", "fax"]
def pede_nome(padrão=""):
nome = input("Nome: ")
if nome == "":
nome = padrão
return(nome)
def pede_telefone(padrão=""):
telefone = input("Telefone: ")
if telefone == "":
telefone = padrão
return telefone
def pede_tipo_telefone(padrão=""):
while True:
tipo = input("Tipo de telefone [%s]: " % ",".join(tipos_de_telefone)).lower()
if tipo == "":
tipo = padrão
for t in tipos_de_telefone:
if t.startswith(tipo):
return t # Retorna o nome completo
else:
print("Tipo de telefone inválido!")
def pede_email(padrão=""):
email = input("Email: ")
if email == "":
email = padrão
return(email)
def pede_aniversário(padrão=""):
aniversário = input("Data de aniversário: ")
if aniversário == "":
aniversário = padrão
return(aniversário)
def mostra_dados(nome, telefones, email, aniversário):
print("Nome: %s" % nome.capitalize())
print("Telefone(s):")
for telefone in telefones:
print("\tNúmero: %15s Tipo: %s" % (telefone[0], telefone[1].capitalize()))
print("Email: %s\nAniversário: %s\n" % (email, aniversário))
def pede_nome_arquivo():
return(input("Nome do arquivo: "))
def pesquisa(nome):
mnome = nome.lower()
for p, e in enumerate(agenda):
if e[0].lower() == mnome:
return p
return None
def novo():
global agenda, alterada
nome = pede_nome()
if pesquisa(nome) != None:
print("Nome já existe!")
return
telefones = []
while True:
numero = pede_telefone()
tipo = pede_tipo_telefone()
telefones.append( [numero, tipo] )
if confirma("que deseja cadastrar outro telefone") == "N":
break
email = pede_email()
aniversário = pede_aniversário()
agenda.append([nome, telefones, email, aniversário])
alterada = True
def confirma(operação):
while True:
opção = input("Confirma %s (S/N)? " % operação).upper()
if opção in "SN":
return opção
else:
print("Resposta inválida. Escolha S ou N.")
def apaga():
global agenda, alterada
nome = pede_nome()
p = pesquisa(nome)
if p != None:
if confirma("apagamento") == "S":
del agenda[p]
alterada = True
else:
print("Nome não encontrado.")
def altera():
global alterada
p = pesquisa(pede_nome())
if p != None:
nome, telefones, email, aniversário = agenda[p]
print("Encontrado:")
mostra_dados(nome, telefones, email, aniversário)
nome = pede_nome(nome) # Se nada for digitado, mantém o valor
for telefone in telefones:
numero, tipo = telefone
telefone[0] = pede_telefone(numero)
telefone[1] = pede_tipo_telefone(tipo)
email = pede_email(email)
aniversário = pede_aniversário(aniversário)
if confirma("alteração") == "S":
agenda[p] = [nome, telefones, email, aniversário]
alterada = True
else:
print("Nome não encontrado.")
def lista():
print("\nAgenda\n\n------")
# Usamos a função enumerate para obter a posição na agenda
for posição, e in enumerate(agenda):
# Imprimimos a posição
print("\nPosição: %d" % posição)
mostra_dados(e[0], e[1], e[2], e[3])
print("------\n")
def lê_última_agenda_gravada():
última = última_agenda()
if última != None:
leia_arquivo(última)
def última_agenda():
try:
arquivo = open("ultima agenda picke.dat", "r", encoding = "utf-8")
última = arquivo.readline()[:-1]
arquivo.close()
except FileNotFoundError:
return None
return última
def atualiza_última(nome):
arquivo = open("ultima agenda picke.dat", "w", encoding = "utf-8")
arquivo.write("%s\n" % nome)
arquivo.close()
def leia_arquivo(nome_arquivo):
global agenda, alterada
arquivo = open(nome_arquivo, "rb")
agenda = pickle.load(arquivo)
arquivo.close()
alterada = False
def lê():
global alterada
if alterada:
print("Você não salvou a lista desde a última alteração. Deseja gravá-la agora?")
if confirma("gravação") == "S":
grava()
print("Ler\n---")
nome_arquivo = pede_nome_arquivo()
leia_arquivo(nome_arquivo)
atualiza_última(nome_arquivo)
def ordena():
global alterada
# Você pode ordenar a lista como mostrado no livro
# com o método de bolhas (bubble sort)
# Ou combinar o método sort do Python com lambdas para
# definir a chave da lista
# agenda.sort(key=lambda e: return e[0])
fim = len(agenda)
while fim > 1:
i=0
trocou = False
while i < (fim - 1):
if agenda[i]>agenda[i + 1]:
# Opção: agenda[i], agenda[i+1] = agenda[i+1], agenda[i]
temp = agenda[i + 1]
agenda[i + 1] = agenda[i]
agenda[i] = temp
trocou = True
i+=1
if not trocou:
break
alterada = True
def grava():
global alterada
if not alterada:
print("Você não alterou a lista. Deseja gravá-la mesmo assim?")
if confirma("gravação") == "N":
return
print("Gravar\n------")
nome_arquivo = pede_nome_arquivo()
arquivo = open(nome_arquivo, "wb")
pickle.dump(agenda, arquivo)
arquivo.close()
atualiza_última(nome_arquivo)
alterada = False
def valida_faixa_inteiro(pergunta, inicio, fim):
while True:
try:
valor = int(input(pergunta))
if inicio <= valor <= fim:
return(valor)
except ValueError:
print("Valor inválido, favor digitar entre %d e %d" % (inicio, fim))
def menu():
print("""
1 - Novo
2 - Altera
3 - Apaga
4 - Lista
5 - Grava
6 - Lê
7 - Ordena por nome
0 - Sai
""")
print("\nNomes na agenda: %d Alterada: %s\n" % (len(agenda), alterada))
return valida_faixa_inteiro("Escolha uma opção: ",0,7)
lê_última_agenda_gravada()
while True:
opção = menu()
if opção == 0:
break
elif opção == 1:
novo()
elif opção == 2:
altera()
elif opção == 3:
apaga()
elif opção == 4:
lista()
elif opção == 5:
grava()
elif opção == 6:
lê()
elif opção == 7:
ordena()