Search code examples
c

Why is my C program not printing anything sometimes from the string inconsistently? (using linked lists)


I'm trying to use linked lists to store the data from the periodic table: name, symbol, and atomic weight. My code is printing correctly for some elements, but the element name is disappearing sometimes. Running the same code multiple times, it's not printing different names at different times. (I messed up the order while giving the inputs, but please ignore that.)

evil image of text that is inaccessible because you can't copypaste and which defeats screen readers

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

typedef struct list{char element[20]; char sym[20];float weight;struct list*next;}list;


int printlist(list *h, char *title){
    printf("%s\n", title);
    while(h!=NULL){
        printf("%s: %s: %f \n", h->element, h->sym, h->weight);
        h = h-> next;   
    }
}

list* create_list(char e[], char s[], float w){
    list * head = malloc(sizeof(list));
    strcpy(head->element,e);
    strcpy(head -> sym,s);
    head -> weight = w;
    head -> next = NULL;
    return head;
}

void add_to_rear(char e[], char s[], float w, list*h){
    while(h->next != NULL){
        h= h-> next;
    }
    list *nn = create_list(e, s, w);
    h -> next = nn;
}

int main(){

    list list_of_atoms;
    list * head = NULL;
    for(int i=0; i<1;i++){
        printf("element %d", i+1);
        char el[20];
        char symbol[2];
        float atwt;
        scanf("%s", el);
        scanf("%s", symbol);
        scanf("%f", &atwt);
        head = create_list(el, symbol, atwt);
    }
    for(int i=1; i<10;i++){
        printf("element %d", i+1);
        char el[20];
        char symbol[2];
        float atwt;
        scanf("%s", el);
        scanf("%s", symbol);
        scanf("%f", &atwt);
        add_to_rear(el, symbol, atwt, head);
    }
    printlist(head, "First 10 elements");
    return 0;

}

Solution

  • You allocate and fill in a bunch of lists (which is a misnomer; each struct is actually info about an element) and then discard them ... head ends up pointing to the last element entered, and its next field is NULL. You then read in all the elements again (why?), scanning each time to the end of the list and appending the element--which is an O(N*N) operation. (I suspect that you actually entered an empty list for the first loop, and then entered your 10 elements for the second loop, but it's impossible to tell because you provided the input as a truncated screen shot. Please don't do that. Instead, copy the text from your CMD window.) Edit: Now I see that your first loop actually only runs one time. It's like you wrote it one way, then changed your mind and wrote it another way, but left the old code there.

    The reason the output is wrong is that you are using scanf to read 2-character symbols plus a terminating NUL into symbol[2], which isn't big enough. This is undefined behavior, but what it is probably doing is overwriting the first byte of the element name with a NUL. Notice that all the elements with 2-letter symbols are missing the element name and the ones with 1-letter symbols are not.