Problem with linked list of dynamic implementation in C

2

Hello, guys, I have two questions:

  • Why am I unable to print any list?

  • How do I go through a given list, headless and without sentinel, backwards, using this implementation?

  • #include <stdio.h>
    #include <stdlib.h>
    #include <malloc.h>
    #include <string.h>
    
    typedef int bool;
    enum { false, true };
    
    // elemento da lista
    typedef struct estr {
            char letra;
            struct estr *prox;
    } NO;
    
    
    typedef struct{
        NO* inicio;
    }LISTA;
    
    void inicializarLista(LISTA *l){
        l->inicio = NULL;
    }
    
    void criarLista(LISTA *l, char plvr[]){
        NO* ult = NULL;
        for(int i = 0; i < strlen(plvr); i++){
            NO* novo = (NO*)malloc(sizeof(NO));
            novo->letra = plvr[i];
            novo->prox = NULL;
            if(ult) ult->prox = novo;
            else l->inicio = novo;
            ult = novo;
        }
    }
    
    void imprimirLista(LISTA l){
        NO* p = l.inicio;
        while(p){
        printf("%d", p->letra);
        p = p->prox;
        }
    }
    
    int main() {
        LISTA l;
        inicializarLista(&l);
        char palavra = "caio";
        fgets(palavra, 3, stdin);
        criarLista(&l, palavra);
        imprimirLista(l);
    
        return 0;
    }
    
        
    asked by anonymous 02.09.2017 / 16:45

    1 answer

    2

    Your code has only two stupid little things.

  • That from here:

        char palavra = "caio";
        fgets(palavra, 3, stdin);
    

    That's not right because palavra is char , not char * or char [] . I think what you wanted was this:

        char palavra[] = "caio";
    
  • This detail:

        printf("%d", p->letra);
    

    I think you wanted to use %c instead of %d .

  • With these changes (and also corrections to the indentation), your code looks like this:

    #include <stdio.h>
    #include <stdlib.h>
    #include <malloc.h>
    #include <string.h>
    
    typedef int bool;
    enum { false, true };
    
    // elemento da lista
    typedef struct estr {
        char letra;
        struct estr *prox;
    } NO;
    
    typedef struct {
        NO *inicio;
    } LISTA;
    
    void inicializarLista(LISTA *l) {
        l->inicio = NULL;
    }
    
    void criarLista(LISTA *l, char plvr[]) {
        NO *ult = NULL;
        for (int i = 0; i < strlen(plvr); i++) {
            NO *novo = (NO *) malloc(sizeof(NO));
            novo->letra = plvr[i];
            novo->prox = NULL;
            if (ult) {
                ult->prox = novo;
            } else {
                l->inicio = novo;
            }
            ult = novo;
        }
    }
    
    void imprimirLista(LISTA l) {
        NO *p = l.inicio;
        while(p) {
            printf("%c", p->letra);
            p = p->prox;
        }
    }
    
    int main() {
        LISTA l;
        inicializarLista(&l);
        char palavra[] = "caio";
        //fgets(palavra, 3, stdin);
        criarLista(&l, palavra);
        imprimirLista(l);
    
        return 0;
    }
    

    Here is the output produced:

    caio
    

    See here working on ideone.

    In this list, nodes have pointers only for the next elements, not the previous ones. This is a one-way street. Thus, the best solution to be able to go backwards is to have in its structure NO the pointer to the previous element and in LISTA the pointer to the last element. Without doing this, to go back and forth from this list, there are even a few tricks you can do, but none of them are efficient, because in all of them you will have to first go through from front to back and use some auxiliary memory with a proportional size to the size of the list. So, the best thing is to have the pointer to the previous element.

    One final thing is that strlen is not very efficient because it is implemented as a while or for that traverses the string looking for the null terminator and counting the number of iterations made, which is very inefficient in the case of a string that contains an entire book, for example. Of course in your case, because the string is small, the impact on performance is negligible, but it's good to avoid its use to create the habit of always doing the best. So you could pass a tamanho parameter to the criarLista function to avoid having to call the strlen function.

        
    02.09.2017 / 17:30