0

I have to read data from a .txt file, and then sort them.

I created my method on an other C file, and it worked perfectly, but when I import it, I got this Segmentation fault error.

I try each line of my program, and it seems that my problem is coming from these two functions :

ListScore* fillScore(){
    ListScore *list=malloc(sizeof(*list));
    FILE* f =NULL;
    int score;
    char name[20];
    f= fopen("score.txt", "r");
    if (f==NULL || list==NULL) {
        perror("fopen or list Null");
        exit(EXIT_FAILURE);
    }

    while(fscanf(f,"%d%s",&score,name)==2){
        insertElem(list,score,name);
    }
    fclose(f);
    bubbleSort(list);
    return list;
}

and

void bubbleSort(ListScore* list){
Score_s *get=list->first;
Score_s *move;
/* Checking for empty list */
if (list->first == NULL)
    {return;}

else{
    while(get->next!=NULL){
        move=list->first;
        while(move->next!=NULL){
            if(move->score<move->next->score){
                swap(move,move->next);
            }
            move=move->next;
            printTest();
        }
        get=get->next;
    }
}

}

and debugger show me this condition as the problem if(move->score<move->next->score); I can't understand why on an external C file, it worked, but in a complex project (with include.h) it doesn't work.

Thanks in advance.

EDIT : My struct ListScore is defined like this :

typedef struct ListScore{
    Score_s *first;    
}ListScore;

and Score_s like this

typedef struct Score_s Score_s;
struct Score_s{
    char name[20];
    int score;
    Score_s *next;
};

EDIT 2 : Here's the minimal example, but it works perfectly on it's own... as said in the beginning of this question;

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

typedef struct Score_s Score_s;

struct Score_s{
    char name[20];
    int score;
    Score_s *next;
};

typedef struct ListScore{
    Score_s *first;    
}ListScore;



void insertElem(ListScore* list,int s,char n[]){
    if(list==NULL){
        exit(EXIT_FAILURE);
    }
    Score_s* new;
    new=malloc(sizeof(*new));
    strcpy(new->name,n);
    new->score=s;
    new->next=list->first;
    list->first=new;
}

void swap(Score_s *a,Score_s *b){
    int tmp=a->score;
    a->score=b->score;
    b->score=tmp;
    char tmpS[20];
    strcpy(tmpS,a->name);
    strcpy(a->name,b->name);
    strcpy(b->name,tmpS);
}


void bubbleSort(ListScore* list){
    Score_s *get=list->first;
    Score_s *move;

    /* Checking for empty list */
    if (list->first == NULL)
        {return;}

    else{
        while(get->next!=NULL){
            move=list->first;
            while(move->next!=NULL){
                if(move->score<move->next->score){
                    swap(move,move->next);
                }
                move=move->next;
            }
            get=get->next;
        }
    }

}


void fillScore(){
    ListScore *list=malloc(sizeof(*list));
    FILE* f =NULL;
    int score;
    char name[20];
    f= fopen("score.txt", "r");
    if (f==NULL || list==NULL) {
        perror("fopen or list Null");
        exit(EXIT_FAILURE);
    }

    while(fscanf(f,"%s%19d",name,&score)==2){
        insertElem(list,score,name);
    }
    
    Score_s* new;
    new=malloc(sizeof(*new));
    new=list->first;
   
    fclose(f);
    printf("\n\n");
    bubbleSort(list);
    new=list->first;
    while(new!=NULL){
        printf("%s %d\n",new->name,new->score);
        new=new->next;
    }
    free(list);


}

int main(int argc, char const *argv[])
{
    fillScore();
    return 0;
}

Content of score.txt :

pat 20
ananna 20
radis 19
gg 121
nique 236
perie 125
aziz 127
telma 36
coc 1
aie 6
prout 236

and this is the output :

prout 236
nique 236
aziz 127
perie 125
gg 121
telma 36
ananna 20
pat 20
radis 19
aie 6
coc 1
Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
Cariamole
  • 296
  • 2
  • 10
  • 2
    What happens when you step through your program line-by-line with a debugger? – Andrew Henle Apr 30 '22 at 10:32
  • 2
    Have you tried running your code line by line in a debugger while monitoring the values of all variables, in order to determine at which point your program stops behaving as intended? If you did not try this, then you may want to read this: [What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/q/25385173/12149471) You may also want to read this: [How to debug small programs?](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) – Andreas Wenzel Apr 30 '22 at 10:38
  • 1
    Can you show us the definition of `ListScore`? – Andreas Wenzel Apr 30 '22 at 10:40
  • It comes in fact from my bubbleSort function, I will edit my question ! if(move->scorenext->score){ is the line causing trouble, if I believe gdb. – Cariamole Apr 30 '22 at 10:47

1 Answers1

1

In the function fillScore, you are not giving list->first any value, so that its value is indeterminate. Therefore, after adding elements to the linked list using the function insertElem, the last element of your linked list does not have a NULL pointer, but instead has a pointer with an indeterminate value. Eventually, the function bubbleSort will attempt to deference this indeterminate value, which is probably causing your segmentation fault.

Therefore, you should set list->first to NULL.

In your question, you posted two substantially different versions of the function fillScore. Since I do not know which one you are using, I cannot tell whether there are other issues in the code that you are using.

Also, the line

while(fscanf(f,"%s%19d",name,&score)==2){

does not make sense. You probably intended to write

while(fscanf(f,"%19s%d",name,&score)==2){

instead.

It is also worth noting that your program contains several memory leaks. You are freeing all the memory allocated by the line

ListScore *list=malloc(sizeof(*list));

but all the memory allocated by other calls to malloc in your program are not being freed. However, this is not the reason for the segmentation fault that you are having.

After fixing all of the issues mentioned above, your code should look like this:

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

typedef struct Score_s Score_s;

struct Score_s{
    char name[20];
    int score;
    Score_s *next;
};

typedef struct ListScore{
    Score_s *first;    
}ListScore;

void insertElem(ListScore* list,int s,char n[]){
    if(list==NULL){
        exit(EXIT_FAILURE);
    }
    Score_s* new;
    new=malloc(sizeof(*new));
    strcpy(new->name,n);
    new->score=s;
    new->next=list->first;
    list->first=new;
}

void swap(Score_s *a,Score_s *b){
    int tmp=a->score;
    a->score=b->score;
    b->score=tmp;
    char tmpS[20];
    strcpy(tmpS,a->name);
    strcpy(a->name,b->name);
    strcpy(b->name,tmpS);
}


void bubbleSort(ListScore* list){
    Score_s *get=list->first;
    Score_s *move;

    /* Checking for empty list */
    if (list->first == NULL)
        {return;}

    else{
        while(get->next!=NULL){
            move=list->first;
            while(move->next!=NULL){
                if(move->score<move->next->score){
                    swap(move,move->next);
                }
                move=move->next;
            }
            get=get->next;
        }
    }

}

void fillScore(){
    ListScore *list=malloc(sizeof(*list));
    list->first = NULL;
    FILE* f =NULL;
    int score;
    char name[20];
    f= fopen("score.txt", "r");
    if (f==NULL || list==NULL) {
        perror("fopen or list Null");
        exit(EXIT_FAILURE);
    }

    while(fscanf(f,"%19s%d",name,&score)==2){
        insertElem(list,score,name);
    }
   
    fclose(f);

    bubbleSort(list);

    Score_s *new = list->first;
    while(new!=NULL){
        printf("%s %d\n",new->name,new->score);

        //remember pointer to previous node so that
        //it can be freed after use
        Score_s *prev = new;

        new=new->next;

        //free the pointer to the previous node
        free( prev );
    }
    free(list);
}

int main( void )
{
    fillScore();
    return 0;
}

With the input specified in the question, this program has the following output:

prout 236
nique 236
aziz 127
perie 125
gg 121
telma 36
ananna 20
pat 20
radis 19
aie 6
coc 1

As you can see, all lines are correctly sorted by score.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
  • In fact, I think it comes possibly from an overflow : I can read all the first line of my txt file. – Cariamole Apr 30 '22 at 11:02
  • @Cariamole: Now that you have shown the definition of `Score_s`, I can see that `new->name` does have sufficient space, so that is not the problem. However, the possibility of a buffer overflow in the `fscanf` line is still there. If you change the `fscanf` line to what I suggested (by adding `19`), does the problem disappear? – Andreas Wenzel Apr 30 '22 at 11:05
  • It doesn't change the output : Still a segmentation fault. Thank you for your time and also, sorry for these late responses. – Cariamole May 02 '22 at 17:28
  • @Cariamole: I have now reformulated my entire answer due to your updated question. – Andreas Wenzel May 02 '22 at 20:55