简体   繁体   中英

linked list printf("%d\n",tasks_head->head->tid) Segmatation fault

I have this code and i want to print the tid of each node. I have segmatation fault in this for loop printf("%d\\n",tasks_head->head->tid); And i am not sure if the task_count[] works as i want. I want to save a counter++ in each position of the array.

struct Tasks
{

    int tid;                     
    int difficulty;               
    struct Tasks *next;          
};

struct Head_GL
{

    int tasks_count[3];          
    struct Tasks *head;           
};

struct Head_GL *tasks_head=NULL;

int num=0;

int insert_task(int tid, int difficulty){

    num++;
    struct Tasks *prev=NULL;
    struct Tasks *temp=NULL;
    struct Tasks *new=(struct Tasks*)malloc(sizeof(struct Tasks));


    tasks_head=(struct Head_GL*)malloc(sizeof(struct Head_GL));
    tasks_head->head=(struct Tasks*)malloc(sizeof(struct Tasks));

    tasks_head->tasks_count[0]=0;
    tasks_head->tasks_count[1]=0;
    tasks_head->tasks_count[2]=0;
    tasks_head->head->difficulty=0;
    tasks_head->head->tid=0;
    tasks_head->head->next=NULL;

    if(new==NULL)
        return 0;
    new->tid = tid;
    new->difficulty = difficulty;
    new->next = NULL;

    if(difficulty==1)
        tasks_head->tasks_count[0]++;
    else if(difficulty==2)
        tasks_head->tasks_count[1]++;
    else
        tasks_head->tasks_count[2]++;
    

    if(tasks_head==NULL){
        tasks_head->head = new;
        return 1;
    }
    if( tasks_head->head->difficulty > difficulty){
        new->next = tasks_head->head;
        tasks_head->head= new;
        return 1;
    }
    else{
        prev = tasks_head->head;
        temp = tasks_head->head->next;
        while(temp != NULL && temp->difficulty < difficulty){
            prev = temp;
            temp = temp->next;
        }
        if(temp==NULL){
            prev->next = new;
            return 1;
        }
        else{
            new->next = temp;
            prev->next = new;
            return 1;
        }
    }
}


int main(){
    
    printf("hello1\n");
    
    if(1==insert_task(1,1))
        printf("alo");

    if(1==insert_task(4,1))
        printf("alo");

    if(1==insert_task(3,2))
        printf("alo\n");


    printf("%d\n",num);

    for(int i=0; i<num; i++){
        printf("%d\n",tasks_head->head->tid);
        tasks_head->head=tasks_head->head->next;
    }
/*

    for(int i=0; i<3; i++){
        printf("%d",tasks_head->tasks_count[i]);
    }*/
    return 0;
}

There are a few problems with this code, but the most important is how you are affecting tasks_head.

At present you are malloc'ing a new tasks_head each time you enter insert_task, and recreating the head element, with these two lines:-

tasks_head=(struct Head_GL*)malloc(sizeof(struct Head_GL));
tasks_head->head=(struct Tasks*)malloc(sizeof(struct Tasks));

Normally you would either do this once, in a separate call to an initialisation function, or you can do it within insert_task by checking if it has already been performed.

You don't really need to create "head" separately, as the head will be the first "new" when you initialise the tasks_head global variable. So if you move this section of code down to below the creation of the "new" task, then you can assign it directly to the head.

If we look at the code where you are inserting the item into the linked list based upon its difficulty, then you can see that you are already doing this:-

if(tasks_head==NULL){
    tasks_head->head = new;
    return 1;
}

So the creation of a separate "head" is totally unnecessary.

The check here, by the way is exactly the check you would want to perform the once-off initialisation of "tasks_head", so if we take your code from above and move it into this section, then you will not keep reseting your global.

The downside of moving the initialisation, however, is that you've already tried to adjust the task difficulty count, so this also needs to come below, and we'll need to add an equivalent for the init case.

If you put all of those changes together you get the following:-

int insert_task(int tid, int difficulty){
    num++;
    struct Tasks *prev=NULL;
    struct Tasks *temp=NULL;
    struct Tasks *new=(struct Tasks*)malloc(sizeof(struct Tasks));

    if(new==NULL)
        return 0;

    new->tid = tid;
    new->difficulty = difficulty;
    new->next = NULL;

    if(tasks_head==NULL){
        tasks_head=(struct Head_GL*)malloc(sizeof(struct Head_GL));
        tasks_head->head=(struct Tasks*)malloc(sizeof(struct Tasks));
        tasks_head->tasks_count[(difficulty != 1 && difficulty != 2)?2:difficulty-1]=1;
        tasks_head->head = new;
        return 1;
    }

    if(difficulty==1)
        tasks_head->tasks_count[0]++;
    else if(difficulty==2)
        tasks_head->tasks_count[1]++;
    else
        tasks_head->tasks_count[2]++;

    if( tasks_head->head->difficulty > difficulty){
        new->next = tasks_head->head;
        tasks_head->head = new;
        return 1;
    }
    else{
        prev = tasks_head->head;
        temp = tasks_head->head->next;
        while(temp != NULL && temp->difficulty < difficulty){
            prev = temp;
            temp = temp->next;
        }
        if(temp==NULL){
            prev->next = new;
            return 1;
        }
        else{
            new->next = temp;
            prev->next = new;
            return 1;
        }
    }
}

The task_count difficulty mapping looks a little odd but I've tried to replicate your current behaviour, where a task of difficulty 1 is set to 0 and 2 is set to 1 and everything else is set to 2. I've done that with this slightly funky line using a tenery operator:

tasks_head->tasks_count[(difficulty != 1 && difficulty != 2)?2:difficulty-1]=1;

But it might just be that you want:

tasks_head->tasks_count[difficulty-1]=1;

if your task difficulty is only in the range 1-3.

Lastly we need to look at your loops in your main method which are currently modifying the global variable while trying to traverse the linked list.

for(int i=0; i<num; i++){
    printf("%d\n",tasks_head->head->tid);
    tasks_head->head=tasks_head->head->next;
}

I think you want to think about using a pointer to traverse this like the following:-

for(struct Tasks *p = tasks_head->head; p != NULL; p = p->next){
    printf("%d\n", p->tid);
}

I'll leave you to think about the second loop to work out how you might wish to do something similar.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM