簡體   English   中英

無法使用 while(1) 循環遍歷雙向鏈表 - 分段錯誤

[英]Failing to iterate over a doubly linked list with a while(1) loop - segmentation error

我第一次來這里和初學者,所以請耐心等待。

我得到了一個處理雙向鏈表的任務,我們得到了兩個打印函數,可以正向和反向打印鏈表。 無論如何,我們都不允許更改這些功能。

我無法通過while(1)傳遞給它的鏈表。 我做了一個測試 function ,它用while(pointer != NULL)迭代列表,效果很好。

有什么建議么?

這是我的主要 function。

FILE *fp;

struct node{
    int data;
    struct node* prev;
    struct node* next;
};
typedef struct node* listPointer;
listPointer headNode = NULL;
listPointer tailNode = NULL;


void delete(listPointer *head, listPointer removalNode);
//int traverseList(listPointer head, int data);
listPointer insertBefore(listPointer *head, listPointer nextNode, listPointer insertionNode);
listPointer findPosition(listPointer *head, int data);
listPointer findNode(listPointer *head, int data);
listPointer insertAtHead(listPointer *head, listPointer insertionNode);
listPointer insertAtBack(listPointer *head, listPointer insertionNode);
listPointer createNode(int data);
void print_forward(listPointer list);
void print_reverse(listPointer list);

void sortedInsert(listPointer *head,listPointer *tail,int data)
{

    listPointer p = malloc(sizeof(listPointer));
    listPointer temp = malloc(sizeof(listPointer));

    p->data = data;
    p->next = NULL;

    if ((*head) == NULL)
    {
        (*head) = p;
        (*tail) = p;
        (*head)->prev = NULL;
        return;
    }

    if ((p->data) < ((*head)->data))
    {
        p->prev = NULL;
        (*head)->prev = p;
        p->next = (*head);
        (*head) = p;
        return;
    }

    if ((p->data) > ((*tail)->data))
    {
        p->prev = (*tail);
        (*tail)->next = p;
        (*tail) = p;
        return;
    }

    temp = (*head)->next;
    while ((temp->data) < (p->data))
        temp = temp->next;


    (temp->prev)->next = p;
    p->prev = temp->prev;
    temp->prev = p;
    p->next = temp;
}

///test print function
void printlist(listPointer head) // this is a test function
{
  listPointer temp = head;
  while(temp != NULL) // works, but seg fault when is set to while(1) like line 282
  {
    printf("%d - ", temp->data);
    temp = temp->next;
  }
  printf("\n");
}

test print function reverse
void printlist2(listPointer head)
{
  listPointer temp = head;
  while( temp != NULL)
  {
    printf("%d - ", temp->data);
    temp = temp->prev;
  }
  printf("\n");
}


void main(int argc, char** argv)
{
    if(argc != 2)
    {
        fprintf(stderr, "usage: ./mp1 input_filename\n");
        exit(1);
    }

    FILE *fp = fopen(argv[1], "r");

    if(fp == NULL)
    {
        fprintf(stderr, "The input file does not exist.\n");
        exit(1);
    }
    char *op;

    listPointer temp;
    listPointer newnode;
    int data=0;
    int flag=0;
    char c;
    int num;
    ///////////////////////////////////////////////////////// TESTING

    data = 10;
    op = "INSERT";
    sortedInsert(&headNode,&tailNode,data);
    sortedInsert(&headNode,&tailNode,6);
    sortedInsert(&headNode,&tailNode,7);
    printlist(headNode);
    printf("\nhead %d\n",headNode->data);
    printf("tail %d\n",tailNode->data);
    printlist2(tailNode);

    print_forward(headNode); // seg fault
    ///////////////////////////////////////////////////////// TESTING


    /*while(!feof(fp)){
        fscanf(fp,"%s",op);
        fscanf(fp,"%d",&data);
        //printf("%s ",op);
        //printf("%d ",data);
        if(strcmp(op,"INSERT")==0){flag=1;}
        else if(strcmp(op,"DELETE")==0){flag=2;}
        else if(strcmp(op,"ASCEND")==0) {flag=3;}
        else if(strcmp(op,"DESCEND")==0) {flag=4;}
        switch(flag)
        {
            case 1:
                newnode = createNode(data);
                if(headNode == NULL) insertAtHead(&headNode,newnode);
                else{
                    temp = findPosition(&headNode,data);
                    insertBefore(&headNode,temp,newnode);
                }
                break;
            case 2:
                temp = findNode(&headNode,data);
                delete(&headNode,temp);
                break;
            case 3:
                print_forward(headNode);
                break;
            case 4:
                print_reverse(headNode);
                break;
            default: break;
        }
    }*/
    fclose(fp);
}

這是給定的打印功能。

void print_forward(listPointer list) {
    listPointer curr;
    FILE *outfile;
    outfile = fopen("mp1_result.txt", "a");
    if(list) {
        curr = list;
        while(1) {
            fprintf(outfile, "%d ", curr->data);
            printf("%d ", curr->data);
            curr = curr->next;
            if(curr == list) break;
        }
    }
    fprintf(outfile, "\n");
    printf("\n");
    fclose(outfile);
}

void print_reverse(listPointer list) {
    listPointer curr;
    FILE *outfile;
    outfile = fopen("mp1_result.txt", "a");
    if(list) {
        curr = list->prev;
        while(curr != list) {
            fprintf(outfile, "%d ", curr->data);
            printf("%d ", curr->data);
            curr = curr->prev;
        }
        fprintf(outfile, "%d ", curr->data);
        printf("%d ", curr->data);
    }
    fprintf(outfile, "\n");
    printf("\n");
    fclose(outfile);

歡迎和贊賞任何建議!

給定的 function 工作假設循環雙向鏈表,查看檢查if(curr==list) - 它正在檢查第一個條目,而不是 NULL。 由於您的鏈表不是循環的,因此指向 NULL 時會失敗。

導致您在這里遇到段錯誤的主要原因是print_forward function 需要一個循環鏈表,其中頭部和尾部也鏈接在一起。 否則, while(1)循環到達列表末尾時(如您所見),它將出現段錯誤。

逐個構建應用程序通常是一個好主意,像 go 一樣檢查每個位,而不是一次完成整個事情然后試圖找出整個事情出了什么問題,尤其是當你是新手時. 也就是說,我可以看到您的代碼有很多問題:

  • listPointer p = malloc(sizeof(listPointer)); - 這只是它所說的:為指向列表(元素)的指針分配空間,它不會為實際的列表元素騰出空間。
  • 當您檢查新項目是否大於尾部時,您應該使用>= 否則,如果新元素等於尾部,它將失敗此檢查,然后運行循環搜索位置,並最終在它掉出列表末尾時出現段錯誤。
  • 您實際上不需要測試新項目是否小於頭部 - 只需檢查它是否大於(或等於)尾部,如果不是,則遍歷列表中的所有項目以查找哪個大於新項目(從頭部開始)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM