segunda-feira, 2 de abril de 2007

Trabalho com lista encadeada.

/*
Name: Trabalho da disciplina, introdução a linguagem de programação com C
Author: David B., Ana Márcia, Priscilia.
Date: 28/03/07 22:06
Description: Lista encadeada com as funções: adicionar, pesquisar, inserir
e excluir registros.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct cliente {
int codigo;
char nome[35];
struct cliente *proximo;

} *inicio, *ultimo, *novo; // cria 3 ponteiros q iram apontar para a struct.

typedef cliente client;

int cadastrado(char str[35], int k);

int inserir()
{
int j = 0;
char nome2[35];
client p; // crio um ponteiro dentro da função inserir q aponta para a struct(escopo dele se resume a essa funcao,q uandoe la eh finalizada, ele deixa de existir, ao contrario dos outros 3 (inicio, ultimo e novo).
novo = (client *)malloc(sizeof(client)); // armazena espaço na memória para a nova struct.

if(novo == NULL) {
printf("Erro ao tentar alocar memoria.\n");
return 0;
}

printf("Digite o cod do cliente: ");
scanf("%d", &novo->codigo); //copia string q foi entrada pelo usuário no campo nome da struct apontada por novo(cliente)

printf("Digite o nome do novo cliente: ");
scanf("%s", &novo->nome); // atriubui ao campo codigo da struct client o valor q foi digitado pelo usuário

if(cadastrado(novo->nome, novo->codigo) == 1){
printf("Erro ao tentar cadastrar cliente.\nCodigo ou nome já estão em uso.\n");
return 0;
}
novo->proximo = NULL; // garante q o campo proximo da struct client esteja NULL

if(inicio == NULL) /* verifica se o ponteiro para o primeiro elemento da lista foi setado
caso esse if seja verdadeiro, então significa q o ponteiro para a
'cabeça'(primeiro elemento) não foi setado, sendo assim, esses
dados q foram inseridos ainda agora passam a ser apontados pelo
ponteiro(do tpw struct) *inicio(q tem escopo global). */
{
inicio = novo; // atribui um valor para ser o primeiro elemento da lista.
ultimo = novo; // atribui para q o *ultimo aponte para inicio;
}

else // caso o ponteiro inicio nào seja null, logo significa q inicio jah está apontando para
// o primeiro elemento da lista.
{
ultimo->proximo = novo; /* caso esteja sendo a segunda vez q vc chamou essa função
o ponteiro ultimo, continua apontando para a mesma struct
q o ponteiro inicio apontada, sendo assim, mudamos o valor
da primeira struct q foi criar para apontar para a nova struct
q acabou se ser criada
*/
novo->proximo = NULL; /* garantimos q a struct q acabo de ser criada vai apontar
para um valor null, indicando ser o ultimo elemento da lista
*/
ultimo = novo; // as ultimas informacoes digitas são atribuidas ao ponteiro ultimo q tem escopo global,,

}
return 1;

}
int limparmemoria()
{
client *p, *p2;
p2 = p = inicio;
if( inicio != NULL ){ // so liberar se tiver apontando para algum lugar(conhecido(struct))
do {
p2 = p;
p = p->proximo; // aponta para o segundo elemento;
free(p2); // libera posição q p2 está usando
}while(p != NULL);
}
exit(0);
}

int listar()
{
client *p; //cria um ponteiro para a struct cliente
p = inicio; //o ponteiro p agora aponta para o mesmo local q o *inicio está apontando.
if(inicio == NULL){ // se algum usuário jah foi adicionado
printf("Nao há clientes adicionaros\n");
}
else
{
printf("\n\n*** Listando clientes cadastrados ***\n");
do {
printf(" - Codigo: %d\n", p->codigo);
printf(" - Nome: %s\n", p->nome);
printf(" - - - - - -\n");
p = p->proximo; /*pula de uma lista para a outra,,
p agora vai apontar para a struct(client) q o campo proximo dele está apontando.
*/
}while(p != NULL);
}
system("pause");
}

int buscar(char str[35])
{
client *p; //cria um ponteiro para a struct cliente
int v = 0; // variável de verificação, se for setada em 1(cliente foi encontrado), 0(cliente nào foi encontrado);
p = inicio; // ponteiro p, do tpw client, aponta para o primeiro elemento da lista(inicio).
if(inicio == NULL){
printf("Nao há clientes cadastrados\n");
return 0;
}
else {
do {
if(!strcmp(p->nome,str)){ /*strcmp, retorna 0, caso as string seja
iguais,, o modificado !, altera, para q
se sela sejam iguais, o retorno passe a
ser 1 ao inves de 0. */
v++; // incrementa v, q sera verificado posteriormente
break;
}
p = p->proximo; // faz com q o ponteiro p aponte para a próxima struct q o campo proximo esta indicando.
} while(p != NULL);
}
if(v > 0){ // > 0 como foi mencionado,, significa q cliente procura foi encontrado.
printf("Codigo do cliente: %d\n", p->codigo);
printf("Nome do cliente: %s\n", p->nome);
return 1; // retorna 1, foi encontrado
}
else {
printf("Cliente nao encontrado.\n");
return 0;
}
}
int cadastrado(char str[35], int k)
{
client *p; //cria um ponteiro para a struct cliente
int v = 0; // variável de verificação, se for setada em 1(cliente foi encontrado), 0(cliente nào foi encontrado);
p = inicio; // ponteiro p, do tpw client, aponta para o primeiro elemento da lista(inicio).
if(inicio != NULL){
do {
if(!strcmp(p->nome,str) || p->codigo == k){
v++;
break;
}
p = p->proximo; // faz com q o ponteiro p aponte para a próxima struct q o campo proximo esta indicando.
} while(p != NULL);
}
if(v > 0){
return 1; // retorna 1, foi encontrado
}
else {
return 0;
}
}
int alterar(char str[35]) // usa o mesmo principio da funcao bucsar,,
{
client *p;
int v = 0; // variável de verificação.
p = inicio; // ponteiro p, do tpw client, aponta para o primeiro elemento da lista(inicio).
if(inicio == NULL){
printf("Nao há clientes cadastrados\n");
return 0;
}
else {
do {
if(!strcmp(p->nome,str)){
v=1;
break;
}
p = p->proximo; // faz com q o ponteiro p aponte para a próxima struct
} while(p != NULL);
}
if(v > 0){ // caso tenha sido encontrado,, permitie q o usuario entre com novos dados para o cliente.
printf(" - Codigo: %d \n - Cliente: %s\n", p->codigo, p->nome); /* o break foi usado no if() logo
quando a condição se torna verdade,
isso garante q *p está ainda apontando
para a struct da lista q o cliente
foi encontrado.
*/
printf("Alterar codigo do cliente para: \n");
scanf(" %d",&p->codigo);
printf("Alterar nome do cliente para: \n");
scanf(" %s",&p->nome);
return 1;
}
else {
printf("Cliente nao encontrado.\n");
return 0;
}
}
int deletar(char str[35]) {
int r = 0;
client *antes, *atual, *ultimoo, *pass = NULL;
antes = atual = inicio;
do {
if(!strcmp(atual->nome,str)) { // verifica se str está na struct apontada por atual

if (atual == inicio && ultimo == NULL) { // verifica se o q vai ser exlcuido eh o primeiro registro e unico da lista
free(atual); // como eh o único registro, basta usar o free.
inicio = NULL; // inicio agora recebe NULL;
r = 1;
break;
}
else if(atual == inicio) { // verifica se o q vai ser excluido eh o primeiro registro..
inicio = atual->proximo; /* como o atual esta apontando para inicio, antes
de usar o free para esse ponteiro(atual), precisamos garantir
q o inicio continue apontando para o topo da lista,
e o topo da lista agora vai ser a struct q inicio
esta apontando,, logo,, "dizemos" para q o ponteiro
*inicio, aponte para a struct q está indicada pelo
seu campo *proximo
*/
free(atual);
r = 1; // serve para fazer uma verificação,, 1, foi excluído, 2, nào foi excluído.
break;
}
else if (atual->nome == ultimo->nome) { // verifica se é o ultimo elemento da lista
ultimo->proximo = antes; /* garante q o ultimo proximo agora aponte para estruct
antes(a struct q está apontando para ultimo), verificar
fim do "do{}" para maiores detalhes.
*/
antes->proximo = NULL; /* antes passa a ser o ultimo,, por isso o campo antes
agora vai ser alterado para NULL, antes, antes estava
apontando para ultimo, sendo q ultimo vai ser deletado,
opr isso antes vai passar a a pontar para null, */
free(atual);

r = 1;

ultimo = antes;
break;
}
else { // usado quando o registro, não eh o ultimo, não eh o primeiro e não eh o único elemento da lista.
pass = atual; // pass agora aponta para o mesma struct q atual esta apontando.
pass = atual->proximo; // pass passa a apontar para a struct q o campo proximo está indicando.
antes->proximo = pass; /* antes proximo, aponta para pass e pass não está + apontando para atual e
sim para a struct q atual está apontando,, logo,,
antes->proximo q apontava para a struct atual passa a
apontar para pass(q é a struct apontada por atual)
*/
r = 1;
free(atual);
break;
}
}
else {
antes = atual; // depois q esse bloco {} eh executado uma vez,, antes eh sempre a struct q aponta para a struct atual
atual = atual->proximo; // e atual aqui passa a apontar para a struct cliente q o seu campo proximo aponta

}
} while(antes != ultimo);
if(r > 0){ return 1; } else { return 0; }
}

int main()
{
char str[35];
int a;
inicio = ultimo = novo = NULL; // garante q todos os ponteiros seja inicializado como NULL
for(;;)
{
system("cls");
printf("1. Adicionar cliente\n");
printf("2. Listar clientes cadastrados\n");
printf("3. Pesquisar por cliente\n");
printf("4. Excluir cliente\n");
printf("5. Alterar dados do cliente\n");
printf("6. Sair\nOpcao: ");
scanf("%d", &a);
switch(a)
{
case 1 : {
if(inserir() == 1) {
printf("\n\n - Cliente cadastrado com sucesso \n\n\n");
}
else {
printf("\n\n - Código ou nome do cliente jah estao em uso.\n\n\n");
}
system("pause");
break;
}
case 2 : listar(); break;
case 3 : {
printf("Nome do cliente: ");
scanf("%s", &str);
buscar(str);
system("pause");
break;
}
case 4 : {
printf("Nome do cliente que deseja excluir: ");
scanf("%s", &str);
if(deletar(str) == 1)
{
printf("\n\n - Cliente excluido com sucesso. \n\n\n");
}
else
{
printf("\n\n - Não foi possivel excluir cliente. \n\n\n");
}

}
system("pause");
break;
case 5 : {
printf("Nome do cliente: ");
scanf("%s", &str);
alterar(str);
system("pause");
break;
}
case 6 : limparmemoria();
}
}
}

Nenhum comentário: