Ir ao conteúdo
  • Cadastre-se

C lista duplamente encadeada nao compila


Posts recomendados

 não esta compilando e nem sei porque mas preciso fazer funcionar. e também pretendo completar as funções que faltam.

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

typedef struct dl_elementoLista{
    char *dado;
    struct dl_elementoLista *anterior;
    struct dl_elementoLista *seguinte;
} dl_elemento;

typedef struct dl_ListaDetectada{
    dl_elemento *inicio;
    dl_elemento *fim;
    int tamanho;
} dl_Lista;

/* inicialização da lista */
void inicializacao (dl_Lista * lista);
dl_elemento *aloc (dl_elemento * novo_elemento);

/* INSERÇÃO */
int ins_em_uma_lista_vazia (dl_Lista * lista, char *dado);
int ins_inicio_lista (dl_Lista * lista, char *dado);
int ins_fim_lista (dl_Lista * lista, char *dado);
int ins_depois (dl_Lista * lista, char *dado, int pos);
int ins_antes (dl_Lista * lista, char *dado, int pos);


/* REMOÇÃO */
int REMOV(dl_Lista *lista, int pos);
void exibe (dl_Lista * lista);

/**************************/
void exibe_inv (dl_Lista * lista);
void destruir (dl_Lista * lista);

void inicializacao (dl_Lista * lista){
    lista->inicio = NULL;
    lista->fim = NULL;
    lista->tamanho = 0;
}

int insercao_em_uma_lista_vazia (dl_Lista * lista, char *dado){
    dl_elemento *novo_elemento;
    if ((novo_elemento = aloc(novo_elemento))==NULL)
        return -1;
    strcpy(novo_elemento->dado, dado);
    novo_elemento->anterior = NULL;
    novo_elemento->seguinte = NULL;
    lista->inicio = novo_elemento;
    lista->fim = novo_elemento;
    lista->tamanho++;
    return 0;
}

int ins_inicio_lista (dl_Lista * lista, char *dado){
    dl_elemento *novo_elemento;
    if ((novo_elemento = aloc(novo_elemento))==NULL)
        return -1;
    strcpy(novo_elemento->dado, dado);
    novo_elemento->anterior = NULL;
    novo_elemento->seguinte = lista->inicio;
    lista->inicio->anterior = novo_elemento;
    lista->inicio = novo_elemento;
    lista->tamanho++;
    return 0;
}

int ins_fim_lista (dl_Lista * lista, char *dado){
    dl_elemento *novo_elemento;
    if ((novo_elemento = aloc(novo_elemento))==NULL)
        return -1;
    strcpy(novo_elemento->dado, dado);
    novo_elemento->seguinte = NULL;
    novo_elemento->anterior = lista->fim;
    lista->fim->seguinte = novo_elemento;
    lista->fim = novo_elemento;
    lista->tamanho++;
    return 0;

}

/*
int ins_depois (dl_Lista * lista, char *dado, int pos){

}
*/
/*
int ins_antes (dl_Lista * lista, char *dado, int pos){

}
*/

int remov(dl_Lista *lista, int pos){
    int i;
    dl_elemento *remov_elemento, *em_andamento;
    if (lista->tamanho == 0)
        return -1;
    if (pos == 1){
        remov_elemento = lista->inicio;
        lista->inicio = lista->inicio->seguinte;
        if(lista->inicio == NULL)
            lista->fim = NULL;
        else
            lista->inicio->anterior=NULL;
    }else if(pos == lista->tamanho){
        remov_elemento = lista->fim;
        lista->fim->anterior->seguinte = NULL;
        lista->fim = lista->fim->anterior;
    }else{
        em_andamento = lista->inicio;
        for (i = 1; i < pos; ++i)
            em_andamento = em_andamento->seguinte;
        remov_elemento = em_andamento;
        em_andamento->anterior->seguinte = em_andamento->seguinte;
        em_andamento->seguinte->anterior = em_andamento->anterior;
    }
    free(remov_elemento->dado);
    free(remov_elemento);
    lista->tamanho--;
    return 0;
}

void destruir(dl_Lista *lista){

}

dl_elemento *aloc (dl_elemento * novo_elemento){

}


int remov(dl_Lista *lista, int pos);

void exibe(dl_Lista *lista){

}

/*
void exibe_inv(dl_Lista *lista){

}
*/
int menu (dl_Lista *lista){
    int escolha;
    if (lista->tamanho == 0){
        printf ("1. Adição do 1° elemento\n");
        printf ("2. Fechar\n");
    } else{
        printf ("1. Adição no início da lista\n");
        printf ("2. Adição no final da lista\n");
        printf ("3. Adição antes da posição especificada\n");
        printf ("4. Adição depois da posição especificada\n");
        printf ("5. Remoção da posição especificada\n");
        printf ("6. Destruir a lista\n");
        printf ("7. Fechar\n");
    }
    printf ("\n\nFaça sua escolha: ");
    scanf ("%d", &escolha);
    getchar();
    if(lista->tamanho == 0 && escolha == 2)
        escolha = 7;
    return escolha;
}

int main (void) {
    setlocale(LC_ALL, "Portuguese");
    int escolha = 0, pos;
    char *dado;
    dado = malloc(50);
    dl_Lista *lista;
    dl_elemento *pilote = NULL;
    lista = (dl_Lista *) malloc (sizeof(dl_Lista));
    inicializacao(lista);
    while( escolha!= 7){
        escolha = menu(lista);
        switch(escolha){
            case 1:
                printf("Entre um elemento: ");
                scanf("%s",dado);
                getchar();
                if(lista->tamanho == 0)
                    insercao_em_uma_lista_vazia(lista,dado);
                else
                    ins_inicio_lista (lista, dado);
                printf("%d elementos: início=%s,fim=%s ",
                       lista->tamanho,
                       lista->inicio->dado,
                       lista->fim->dado);
                exibe(lista);
                break;
            case 2:
                printf("Entre um elemento: ");
                scanf("%s",dado);
                getchar();
                ins_fim_lista (lista, dado);
                printf("%d elementos: início=%s,fim=%s ",
                       lista->tamanho,
                       lista->inicio->dado,
                       lista->fim->dado);
                exibe(lista);
                break;
            case 3:
                if(lista->tamanho == 1){
                    printf("Utilizar a inserção no início ou no fim (Entrar Menu: 1 ou 2)\n");
                    break;
                }
                printf("Entre um elemento:");
                scanf("%s",dado);
                getchar();
                do{
                    printf("Entre a posição:");
                    scanf("%d",&pos);
                }while (pos < 1 || pos > lista-> tamanho);
                getchar();
                ins_antes(lista,dado,pos);
                printf("%d elementos: início=%s fim=%s ",
                       lista->tamanho,
                       lista->inicio->dado,
                       lista->fim->dado);
                exibe(lista);
                break;
            case 4:
                if(lista->tamanho == 1){
                    printf("Utilizar a inserção no início ou no fim (Entrar Menu: 1 ou 2)\n");
                    break;
                }
                printf("Entre um elemento : ");
                scanf("%s",dado);
                getchar();
                do{
                    printf("Entre a posição: ");
                    scanf("%d",&pos);
                }while (pos < 1 || pos > lista->tamanho);
                getchar();
                ins_depois(lista,dado,pos);
                printf("%d elementos: início=%s,fim=%s ",
                       lista->tamanho,
                       lista->inicio->dado,
                       lista->fim->dado);
                exibe(lista);
                break;
            case 5:
                do{
                    printf("Entre a posição: ");
                    scanf("%d",&pos);
                }while (pos < 1 || pos > lista->tamanho);
                getchar();
                remov(lista,pos);
                if(lista->tamanho != 0)
                    printf("%d elementos: início=%s,fim=%s ",
                           lista->tamanho,
                           lista->inicio->dado,
                           lista->fim->dado);
                else
                    printf("posição vazia: %d elementos",
                           lista->tamanho);
                exibe(lista);
                break;
            case 6:
                destruir(lista);
                printf("a posição foi destruída: %d elementos\n",
                       lista->tamanho);
                break;
        }
    }
    return 0;
}

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

int insercao_em_uma_lista_vazia(dl_Lista* lista, char* dado) {
    dl_elemento* novo_elemento;
    if ((novo_elemento = aloc(novo_elemento)) == NULL)
        return -1;

  ...

Meu compilador por exemplo reclama desse tipo de construção. Afinal novo_elemento não foi inicializado antes de entrar na comparação. E não é uma prática recomendada afinal. Inicialize TODAS as variáveis.

 

Recomendo também evitar atribuições dentro de condições. Acaba dificultando a leitura apenas. Isso se você não esquecer um parenteses para manter a prioridade correta. É mais problema do que solução. Compare:

int insercao_em_uma_lista_vazia(dl_Lista* lista, char* dado)
{
    dl_elemento* novo_elemento = aloc();
    if (novo_elemento == NULL) return -1;

  ...

Veja como fica mais fácil de ler. E mais seguro.

 

Não é comum:

  • ter uma função para criar um elemento --- a tal aloc()
  • ter um parâmetro na função aloc() que parece fazer sempre a mesma coisa. Ela não parece precisar de um argumento de entrada, como seria o caso se pudesse criar um número arbitrário de elementos... Apenas importa o valor retornado
  • ter uma função para inserir um elemento numa lista vazia que chama uma função que aloca um nó da lista

E em geral é mais seguro retornar não int mas sim o endereço da lista, que pode ter mudado.

 

Em geral você escreve apenas

    LISTA* inserir( DADO*, LISTA*);

já que é a acepção mais comum em português: vai inserir um dado na lista, então passa o endereço do dado e o endereço da lista. Sugiro inverter os parâmetros. E recebe o endereço de início da lista, que pode ter mudado

 

E declarar os dados como um tipo interno, ou o mais comum, (void*). A razão é muito simples: você não quer editar essas funções para tratar a próxima lista no exercício da semana que vem... Sabe, a tal lista de livros, a playlist, a lista de produtos na nota fiscal... Mais do mesmo... Se prepare...

 

Compare:

    typedef char DADO;  ja serviria

Apenas isso e você poderia usar

typedef struct dl_elementoLista {
    DADO*  dado;
    struct dl_elementoLista* anterior;
    struct dl_elementoLista* seguinte;
} dl_elemento;

// ao invés de 

typedef struct dl_elementoLista {
    char* dado;
    struct dl_elementoLista* anterior;
    struct dl_elementoLista* seguinte;
} dl_elemento;

// mas veja

int ins_em_uma_lista_vazia(dl_Lista* lista, DADO* dado);
int ins_inicio_lista(dl_Lista* lista, DADO* dado);
int ins_fim_lista(dl_Lista* lista, DADO* dado);
int ins_depois(dl_Lista* lista, DADO* dado, int pos);
int ins_antes(dl_Lista* lista, DADO* dado, int pos);

E ao mudar os dados não precisaria mexer nessas funções.

 

Não use nomes de variáveis nos protótipos. Não são usados.

 

E em geral não é preciso testar se a lista está vazia.

 

Na hora de inserir, se você passa o endereço da lista como NULL --- 0 no popular --- a rotina de inserção cria a lista silenciosamente. Isso permite escrever coisas assim sem ter que pensar

    LISTA* umaLista = inserir( &dado, NULL);     // cria a lista e insere o primeiro registro
    LISTA* umaOutraLista = inserir( NULL, NULL); // cria uma lista vazia

    ...
      
    umaOutraLista = inserir( &lidoAgora, umaOutraLista); // insere algo na segunda lista

E funciona.

 

Se está escrevendo métodos para inserir no fim e no início e na posição, talvez devesse ter um para inserir na ordem e

  • crie na lista um ponteiro para o fim. Porque perder tempo percorrendo a lista para inserir no final se você tem o controle sobre o processo de inserção?

 

adicionado 3 minutos depois

Os protótipos servem para o compilador não para o leitor.

 

Use main() sempre como a primeira função. Em especial se trabalha com mais gente ou se pode pedir ajuda para alguém ler seu programa.

 

E use alguma ordem nas funções, como a ordem alfabética comum. O tempo passa, os programas ficam grandes e tal...

 

 

  • Curtir 3
Link para o comentário
Compartilhar em outros sites

6 minutos atrás, Jorge Curvelo disse:

eu sou novato nessa área de programação mas li tudo que você escreveu e entendi que dá para melhorar muita coisa ne, mas de imediato eu só quero rodar ele do jeito que esta mesmo

 

entenda que tem coisas dessas que eu te expliquei que são importantes justamente para quem está começando ou simplesmente porque se está começando. . Sem essas coisas você vai levar MUITO mais tempo para resolver seu problema.

 

Em particular:

  • não retornando o endereço da lista para funções que podem mudá-lo
  • criando funções sem necessidade, como essas que alocam nós e iniciam a lista
  • criando tipos fixos de dados

E coisas assim. Para um profissional ou um especialista não faz diferença. Apenas existe uma convergência entre esses caras --- e os autores de livros sobre essas coisas --- de modo que os programas acabam quase idênticos, o que provavelmente indica que eu estou certo...

 

Vou ler o resto do seu programa

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Acho que seu programa não está bom. Algumas notas além do que eu já falei, agora que li o resto:

  • apesar de ter uma função inicialização e uma função insere_na_lista_vazia e uma aloc() com parâmetro e tudo, você aloca memória no programa principal, fora (!) dessas funções. É perda de tempo. Imagine se você tivesse duas listas...
  • tem um menu lá, que devia ser a última coisa a escrever e não a primeira, e provavelmente não daquele modo.
  • Sia lista usa um dado char* e não acho que era o que pretendia. Isso é problema: você precisa realocar todos esses dados ou os ponteiros serão invalidados logo em seguida. char* é um ponteiro e precisa alocar antes de colocar na árvore: não pode ir inserindo dados que você acabou de ler, por exemplo. 
  • Adicionar o primeiro elemento não deve ser diferente de adicionar qualquer outro. Ao menos não se não quiser trabalhar a toa.
  • a opção 4 acaba testando para toda a vida se só tem um nó na lista? Não é prático.
            case 4:
                if (lista->tamanho == 1) {
                    printf("Utilizar a inserção no início ou no fim (Entrar Menu: 1 ou 2)\n");
                    break;
                }
    Tem que ter outro jeito de escrever isso
  • O menu bem que poderia simplesmente retornar a opção para tratar no programa que o chamou. Seria bem comum. E é comum porque é mais simples e prático.
  • Em geral se implementa primeiro listar() depois algum inserir() e remover() e se parte daí.

Boa sorte

 

 

adicionado 13 minutos depois

acentos nos comentários e nas mensagens não acrescentam nada num primeiro momento. Não devia perder tempo com essas coisas.

 

Veja esse trecho que poderia estar em seu programa, e vai entender do que estou falando:

    // cria a lista e insere 10 caras
    dl_Lista* teste = NULL;
    for (int i = '0'; i <= '9'; i = i + 1)
    {
        ins_inicio_lista(teste, (char*)&i); // insere 'i'
        exibe(teste);
    };  // for()
    // remove o primeiro 10 vezes
    for (int i = '0'; i <= '9'; i = i + 1) // claro que copiei o loop
    {
        REMOV( teste, 1); // remove o primeiro
        exibe(teste);
    };  // for()
    destruir(teste); // apaga a lista
    exibe(teste); // tenta mostrar a lista vazia

Esse trecho deveria:

  • criar uma lista chamada teste. 
  • inserir os valores '0', '1'... '9' listando o conteúdo entre cada inserção para você ficar mais seguro.
  • remover o primeiro elemento 10 vezes, o que deve deixar a lista vazia. E listando entre cada um pra você acompanhar
  • apagar a lista
  • tentar listar a lista vazia

Assim você progride mais rápido. 

 

Espero que ajude

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!