【问题标题】:linked list printf("%d\n",tasks_head->head->tid) Segmatation fault链表 printf("%d\n",tasks head->head->tide) 分段错误
【发布时间】:2021-02-22 09:03:09
【问题描述】:

我有这段代码,我想打印每个节点的 tid。我在这个 for 循环中有分段错误 printf("%d\n",tasks_head->head->tid); 我不确定task_count[] 是否按我的意愿工作。我想在数组的每个位置保存一个counter++

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;
}

【问题讨论】:

    标签: c pointers data-structures linked-list


    【解决方案1】:

    此代码存在一些问题,但最重要的是您如何影响 tasks_head。

    目前,您每次进入 insert_task 时都会分配一个新的 tasks_head,并使用以下两行重新创建 head 元素:-

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

    通常您可以在单独调用初始化函数时执行一次,或者您可以在 insert_task 中通过检查它是否已经执行来执行此操作。

    您实际上不需要单独创建“head”,因为在初始化 tasks_head 全局变量时,head 将是第一个“新”。因此,如果您将这部分代码移至“新”任务的创建下方,则可以将其直接分配给头部。

    如果我们根据难度查看您将项目插入到链表中的代码,那么您可以看到您已经这样做了:-

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

    所以创建一个单独的“头”是完全没有必要的。

    顺便说一下,这里的检查正是您想要执行“tasks_head”的一次性初始化的检查,所以如果我们从上面获取您的代码并将其移动到此部分,那么您将不会继续重置你的全球。

    然而,移动初始化的缺点是您已经尝试调整任务难度计数,所以这也需要在下面,我们需要为 init 案例添加一个等效项。

    如果将所有这些更改放在一起,您会得到以下结果:-

    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;
            }
        }
    }
    

    task_count 难度映射看起来有点奇怪,但我尝试复制您当前的行为,其中难度为 1 的任务设置为 0,难度为 2 的任务设置为 1,其他一切都设置为 2。我已经完成了使用 Tenery 操作符的这条稍微有点时髦的线:

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

    但这可能只是你想要的:

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

    如果您的任务难度仅在 1-3 范围内。

    最后,我们需要查看您的 main 方法中的循环,这些循环当前在尝试遍历链表时正在修改全局变量。

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

    我认为您想考虑使用指针来遍历它,如下所示:-

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

    我会让您考虑第二个循环,以了解您可能希望如何做类似的事情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-28
      • 2013-10-20
      • 1970-01-01
      • 1970-01-01
      • 2018-03-23
      • 2022-06-24
      • 1970-01-01
      • 2012-04-22
      相关资源
      最近更新 更多