/*
tutty bien?
ViM is great!
* Desenvolvido por Luís Bastião Silva <luis.kop@gmail.com>
r00Ls *NIX* it rocks! GNU/Linux ao poder! :)
luis@darks$ gcc WORK.C -lstdc++ -lcurses -o listatelefonica
__Lista Telefónica__
getch() e clrscr() > /dev/null */
/*#define CLEAN 1*/ /* UNIX d00D! */
#include <stdio.h>
#include <stdlib.h> /* mallocs / free */
#if defined(CLEAN)
#include <curses.h> /* getch() em *NIX* */
#endif
#include <string.h> /* strlen()/str* */
#define LIMITE 100
/* Estrutura que será usada para criar os nós da lista */
typedef struct lista
{
char nome[255]; /* Nome */
char morada[255]; /* Morada - encher choirissos*/
long int telf; /* Telefone */
int idade; /* idade - encher choirissos */
struct lista *seg_nome; /* Proximo elemento da lista encadeada - Telefonica */
struct lista *seg_telf;
} LTELEF;
typedef LTELEF* No; /* tipo No */
FILE *pf;
/* headers das funcoes */
long int inserir(No *inicio_nome, No *inicio_telf);
void inicializar(No *inicio_nome, No *inicio_telf);
int pedir_valores(No *temp, No *inicio_telf);
long int fazer_links(No *inicio_nome, No *inicio_telf, No *temp);
/* Devolve o No */
No procurar(No *inicio_nome, No *inicio_telf, long int telefone, char nome[], int print, int words);
int listalen(No *inicio_telf);
int listar(char opt, No *inicio_telf, No *inicio_nome);
int getfish(No *inicio_nome, No *inicio_telf);
No noanterior(No *inicio_nome, No *inicio_telf, char tn, long int telefone);
int rmbuild(No *inicio_nome, No *inicio_telf, long int telefone);
int remover(No *inicio_nome, No *inicio_telf,long int telefone);
int fishw(No *inicio_telf);
int main()
{
/* Nós */
No inicio_nome, inicio_telf; /* Ponteiros para o inicio (nome/telf) e para fim(nome/telf) */
int q, p; /* opcao */
long int telefone;
char nome[40];
inicializar(&inicio_nome, &inicio_telf);
while (1) {
printf("\n\n==Opções do PROGRAMA: ");
printf("\n1 -> Inserir novo registo na lista telefonica;\n");
printf("\n2 -> Procurar registo [ by (nome && telf)\n");
printf("\n3 -> Remover registo telefónico\n");
printf("\n4 -> Listar Registos \n"); /* next generation implement it to printer :x -g- */
printf("\n5 -> Guardar registos para ficheiro \n");
printf("\n6 -> Carregar registos de um ficheiro \n");
printf("\n0 -> para sair \n:");
scanf("%d", &q); /* Le a opcao do utilizador */
switch(q) {
case 1: inserir(&inicio_nome, &inicio_telf); break;
case 2:
#ifdef CLEAN
system("clear");
#else
clrscr()s;
#endif
while (1)
{
printf("\n1 - Procurar por NOME\n2 - Procurar por Palavra no Nome\n3 - Procurar por TELEFONE\n0- Sair\n");
scanf("%d",&p);
if (p==1)
{
getchar(); /* limpar o que está no buffer */
printf("Introduza o nome: \n");
fflush(stdin);
gets(nome);
if (procurar(&inicio_nome, &inicio_telf, NULL, nome,1,0)==NULL)
printf("Não foram encontrados registos");
}
else if (p==3)
{
printf("Introduza o numero de telefone: \n");
scanf("%ld",&telefone);
if (procurar(&inicio_nome, &inicio_telf, telefone, NULL,1,0)==NULL)
printf("Não foram encontrados registos");
}
else if (p==2)
{
getchar(); /* buffer > /dev/null */
printf("Introduza a palavra: ");
fflush(stdin);
gets(nome);
if (procurar(&inicio_nome,&inicio_telf, NULL, nome, 1, 1)==NULL)
printf("Não foram encontrados registos");
}
else if (p==0) break;
else printf("Opção invalida");
}
break;
case 3: /* FSCKKK FSSSSSSSCKKKK!! REMOVE DON'T WORKS ! ARGGGGGGG!*/
#ifdef CLEAN
system("clear");
#else
clrscr();
#endif
printf("Introduza o telefone\n");
scanf("%ld", &telefone);
printf("%ld", telefone);
remover(&inicio_nome,&inicio_telf, telefone);
break;
case 4:
#ifdef CLEAN
system("clear");
#else
clrscr();
#endif
while(1) {
printf("\n1 - Listar por nome\n2 - Listar por telefone\n0 - Sair\n");
scanf(" %d",&p);
if (p==1)
{
if (listar('N', &inicio_telf, &inicio_nome)==1) printf("Nao foram encontrados registos");
}
else if (p==2){
if (listar('T', &inicio_telf,NULL)==1) printf("Nao foram encontrados registos");
}
else if(p==0) { break;}
else{ printf("Opcao INVALIDA\n");}
}
break;
case 5: if (fishw(&inicio_telf)==0) printf("Ouve um erro na escrita \n"); break;
case 6: if (getfish(&inicio_nome, &inicio_telf)) printf("Carregou os registos correctamente\n"); break;
case 0: return 0; break;
default: printf("Opcao INVALIDA\n");
}
}
}
void inicializar(No *inicio_nome, No *inicio_telf)
{
*inicio_nome = NULL;
*inicio_telf = NULL;
}
int pedir_valores(No *temp, No *inicio_telf)
{
/*
* Is gets() really "dangerous"?
*
* gets() is dangerous because it does no bounds checking. That means you can easily type in millions of characters, overflowing your storage buffer and overwriting parts of the program. This exploit has been used for years by the Bad Guys to write worms and viruses, hence the warning.
*
* When you're ready to write programs for others to use, do not use gets()! For learning, however, it's okay.
*
* (I may get in trouble for saying that gets() is "okay for learning," but my opinion is that it's easier to deal with gets() than to fumble over a workaround that causes the student to stumble in the learning process.)
*
*
*/
long int aux_telf;
getchar();
fflush(stdin);
printf("\nIntroduza o nome completo ->");
gets((*temp)->nome);
printf("\nIntroduza a morada ->");
gets((*temp)->morada);
do
{
printf("\nIntroduza o telefone ->");
scanf("%ld",&aux_telf);
} while (procurar(NULL,&(*inicio_telf), aux_telf, NULL, 1,0)!=NULL);
(*temp)->telf=aux_telf;
printf("\nIntroduza idade ->");
scanf("%d",&(*temp)->idade);
return 0;
}
/* restruturar Nos e ponteiros
telef = JA EXISTE
casos particulares: inserir o ultimo antes do 1º
*/
/* GUARDA TODOS OS REGISTOS!!
* 0 = insucesso
* 1 = sucesso
* */
int fishw(No *inicio_telf)
{
No aux;
aux=*inicio_telf;
if((pf = fopen("lista.bin", "w+b")) == NULL) /* Abre arquivo binário para escrita */
{
printf("Erro na abertura do arquivo\n");
return 0;
}
while (aux!=NULL)
{
if(fwrite(aux, sizeof(LTELEF), 1,pf) != 1)
{ /* Escreve a estrutura no ficheiro */
printf("Erro na escrita do arquivo!\n");
return 0;
}
aux=aux->seg_telf;
}
fclose(pf);
return 1;
}
/* BUSCAR DADOS */
int getfish(No *inicio_nome, No *inicio_telf)
{
No aux;
if((pf = fopen("lista.bin", "rb")) == NULL)
{
printf("Erro na abertura do arquivo\n");
return 0;
}
while (!feof(pf))
{
aux=(No)malloc(sizeof(LTELEF));
if (fread(aux, sizeof (LTELEF), 1, pf)<1)
{
free(aux);
break;
}
fazer_links(inicio_nome, inicio_telf, &aux);
}
return 1;
}
/* Devolve o numero de telefone; se for igual
* Retorna 0 se os links foram feitos com sucesso ;
* Retorna 1 se a lista está cheia;
* Funcao que estrutura os links;
* Inclusive nos ficheiros, é usada para inserir os registos, neste caso os dados não vem do stdin, mas sim de um ficheiro
* binario de registos.
*/
long int fazer_links(No *inicio_nome, No *inicio_telf, No *temp)
{ int len, valor_inicial;
No aux, ant;
int n_elementos=0;
/* contar o numero de elementos */
n_elementos=listalen(&(*inicio_telf));
if (n_elementos == 0)
{
*inicio_nome=*temp;
*inicio_telf=*temp;
(*inicio_nome)->seg_nome=NULL;
(*inicio_nome)->seg_telf=NULL;
(*inicio_telf)->seg_telf=NULL;
(*inicio_telf)->seg_nome=NULL;
return 0;
}
else if (n_elementos < LIMITE)
{
/* order by (fsck sql, it's ugly) nome */
aux = *inicio_telf;
ant=NULL;
while (aux != NULL)
{
if (aux->telf == (*temp)->telf)
{
free((*temp));
return aux->telf;
}
if (aux->telf <(*temp)->telf)
{
ant = aux;
aux = aux->seg_telf;
}
else
{
break;
}
}
if (ant == NULL)
{
/* o valor está antes do 1º */
(*temp)->seg_telf=*inicio_telf;
*inicio_telf=*temp;
}
else
{
ant->seg_telf=*temp;
(*temp)->seg_telf=aux;
}
aux=*inicio_nome;
ant=NULL;
while (aux != NULL)
{
if (strcmp(aux->nome, (*temp)->nome) < 0)
{
ant = aux;
aux = aux->seg_nome;
}
else
{
break;
}
}
if (ant==NULL)
{
/* antes do primeiro */
(*temp)->seg_nome=*inicio_nome;
*inicio_nome=*temp;
}
else
{
ant->seg_nome=*temp;
(*temp)->seg_nome=aux;
}
}
else
{
printf("A lista está cheia!");
free(&temp);
return 1;
}
/* IMPORTANTE : BUILD LINKS (Apontamentos da aula ) :
antes do primeiro
temp->seg_telf = *inicio_telf;
*inicio_telf = temp;
depois do primeiro
ant=aux;
aux=aux->seg_telf;
*/
/* Escrever no ficheiro */
return 0;
}
/* Inserir valores (Pedir_valores + Fazer_links) */
long int inserir(No *inicio_nome, No *inicio_telf)
{
No temp;
temp = (No)malloc(sizeof(LTELEF));
pedir_valores(&temp, &(*inicio_telf));
fazer_links(inicio_nome,inicio_telf, &temp); /* &(* */
return 0;
/* dá pros gastos */
}
/* Vale a pena dizer?
* Lista por nome e por telefone
*/
int listar(char opt, No *inicio_telf, No *inicio_nome)
{
No aux;
/* Listar por telef */
if (opt=='T')
{
if (listalen(&(*inicio_telf))==0) return 1;
printf("Listar por telefone:\n");
aux = *inicio_telf;
while (aux != NULL)
{
printf("\nREGISTOS:\nNome: %s\nMorada: %s\nTelefone: %ld\nIdade: %d\n",aux->nome, aux->morada, aux->telf, aux->idade);
aux=aux->seg_telf;
}
}
else
{
if (listalen(&(*inicio_telf))==0) return 1;
printf("Listar por nome: \n");
aux = *inicio_nome;
while (aux != NULL)
{
printf("\nREGISTOS:\nNome: %s\nMorada: %s\nTelefone: %ld\nIdade: %d\n",aux->nome, aux->morada, aux->telf, aux->idade);
aux=aux->seg_nome;
}
}
return 0;
}
/* Devolve No anterior
* Refazer por causa do tn e poder tirar, usando o NULL
*
* */
No noanterior(No *inicio_nome, No *inicio_telf, char tn, long int telefone)
{
No aux, actual_f;
if (tn=='T')
{
aux = *inicio_telf;
actual_f=NULL;
while (aux->telf!=telefone)
{
actual_f=aux;
aux=aux->seg_telf;
}
}
else {
aux=*inicio_nome;
actual_f=NULL;
while(aux->telf!=telefone)
{
actual_f=aux;
aux=aux->seg_nome;
}
}
return actual_f;
}
/* Reconstroi os links durante a remoção
* */
int rmbuild(No *inicio_nome, No *inicio_telf, long int telefone)
{
No ant, aux,aux_aux ;
aux = *inicio_telf;
while (aux != NULL)
{
if (aux->telf==telefone)
{
/* mudar para telefone */
if (aux==*inicio_telf){
*inicio_telf=aux->seg_telf;
break;
}
else
{
printf("Telef %d",aux->telf);
ant=noanterior(NULL,&(*inicio_telf), 'T', telefone);
printf("\nNo anterior por telef = %d, no seguinte %d\n", ant->telf, aux->telf);
ant->seg_telf=aux->seg_telf;
break;
}
}
aux=aux->seg_telf;
}
aux_aux=*inicio_nome;
while (aux_aux!= NULL)
{
if (aux_aux->telf==telefone)
{
if (aux_aux==*inicio_nome)
{
*inicio_nome=aux->seg_nome;
break;
}
else {
ant=noanterior(&(*inicio_nome), NULL, 'N', telefone);
ant->seg_nome=aux_aux->seg_nome;
break;
}
}
aux_aux=aux_aux->seg_nome;
}
return 0;
}
/*
* Funcao para remover elementos
* Usa a funcao rmbuild para refazer os links.
* Usa a função procurar para verificar se realmente os elementos existem
*/
int remover(No *inicio_nome, No *inicio_telf,long int telefone)
{
int telem;
char opcao;
No aux, ant, aux_aux;
telem=listalen(&(*inicio_telf));
/* Se não tiver elementos, para a função */
if (telem==0) return 1;
/* Se a função não encontrar os elementos, para por aqui */
if (procurar(&(*inicio_nome),&(*inicio_telf), telefone, NULL,0,0)==NULL) return 0;
if (telefone!=NULL)
{
aux=*inicio_telf;
ant=NULL;
while (aux!=NULL)
{
if (aux->telf==telefone)
{
printf("Foi encontrado o seguinte registo:\n");
printf("Nome: %s\n",aux->nome);
printf("Morada: %s\n",aux->morada);
printf("Telefone: %ld\n",aux->telf);
printf("Idade: %d\n------------\n",aux->idade);
while (1)
{
printf("Deseja Remover?[s/n]");
scanf(" %c",&opcao);
if ((opcao=='S')||(opcao=='s'))
{
printf("Será removido com sucesso !\n");
if (telem==1)
{
free((*inicio_nome));
inicializar(&(*inicio_nome),&(*inicio_telf));
}
else {
rmbuild(&(*inicio_nome),&(*inicio_telf), telefone);
}
break;
}
else if ((opcao=='N')||(opcao=='n'))
{
printf("\nNão será removido !\n");
break;
}
else { printf("Opção inválida\n"); }
}
break;
}
aux=aux->seg_telf;
}
}
if (telem>1)
free(aux);
return 1;
}
/* versao beta:
*Em Fase de testes.
*Poderá eventualmente vir a devolver No ou uma estrutura semelhante que guarde o No do anterior e o No actual.
* Podera devolver só o No anterior
*
* final:
* Devolve No. NULL se nao encontrou nada. Variavel print 1/0, para apresentar output ou não.
* */
No procurar(No *inicio_nome, No *inicio_telf, long int telefone, char nome[], int print, int words)
{
No aux, last;
last=NULL;
if (listalen(&(*inicio_telf))==0) return NULL;
if (telefone==NULL)
{
aux=*inicio_nome;
while(aux != NULL)
{
if (words==0)
{ /* procura por nome */
if (strcmp(aux->nome,nome)==0)
{
if (print==1)
{
printf("-------------\n");
printf("Nome: %s\n",aux->nome);
printf("Morada: %s\n",aux->morada);
printf("Telefone: %ld\n",aux->telf);
printf("Idade: %d\n------------\n",aux->idade);
}
return aux;
}
}
else {
if (strstr(aux->nome, nome)!=NULL)
{
printf("--------------\n");
printf("Nome: %s\n",aux->nome);
printf("Morada: %s\n",aux->morada);
printf("Telefone: %ld\n",aux->telf);
printf("Idade: %d\n------------\n",aux->idade);
last=aux;
}
}
aux=aux->seg_nome;
}
}
else
{
aux=*inicio_telf;
while (aux != NULL)
{
if (aux->telf==telefone)
{
if (print==1)
{
printf("Encontrado:\n");
printf("Nome: %s\n",aux->nome);
printf("Morada: %s\n",aux->morada);
printf("Telefone: %ld\n",aux->telf);
printf("Idade: %d\n------------\n",aux->idade);
}
return aux;
}
aux=aux->seg_telf;
}
}
if (last==NULL)
return NULL;
else
return last;
return NULL;
}
/* Função que devolve o numero de elementos da lista */
int listalen(No *inicio_telf)
{
int n_elem=0;
No aux;
aux=*inicio_telf;
while (aux != NULL)
{
n_elem++;
aux=aux->seg_telf;
}
return n_elem;
}