Problem with linked list of dynamic C implementation

Asked

Viewed 118 times

2

Hello, folks, I have two questions:

  1. Why can’t I print out any list?

  2. How do I scroll through a given list, without head and 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;
}

1 answer

2


Your code only has two silly little problems.

  1. That from here:

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

    That ain’t right 'cause palavra is char, and not char * or char []. I think what you wanted was this:

        char palavra[] = "caio";
    
  2. That detail:

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

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

With these changes (and also corrections in identation), 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, the nodes have pointers only for the next elements, and not for the previous ones. This is a one-way street. Therefore, the best solution to be able to go backwards is to have in its structure NO the pointer to the previous element and LISTA the pointer to the last element. Without doing that, to go back through that list, there are even a few tricks that you can do, but none of them are efficient, because in all of them you will first have to go back and forth and use some auxiliary memory with a size proportional to the size of the list. Therefore, the best thing is to have the pointer to the previous element.

One last detail is that the strlen is not very efficient as 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 quite inefficient in the case of a string that contains an entire book, for example. Of course, in your case, as the string is small, the impact on performance is negligible, but it is good to avoid its use to create the habit of always doing the best way. Therefore, you could pass a parameter tamanho for the function criarLista to avoid having to call the function strlen.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.