【问题标题】:Sorting a linked list based on variable C基于变量 C 对链表进行排序
【发布时间】:2016-07-07 01:48:40
【问题描述】:

我正在尝试创建一个调查数据库,其中链表根据其中一个变量存储调查。在我对调查进行排序时,它仅将排序在第一个节点之后的节点(头部可能是 999 并且仍然是第一个节点),并且在添加元素然后显示所有元素时,我偶尔会看到元素的无限打印。

Sample Code:


void addElement(struct listelement** head_ptr)
{
    int data;
    int inputPPS;
    struct listelement *temp;
    struct listelement *newNode;



    if (*head_ptr == NULL)
    {

        addElement_AtStart(head_ptr);

    }

    else

    {

        temp = *head_ptr;
        newNode = (struct listelement*)malloc(sizeof(struct listelement));

        printf("\nPlease enter your PPS number (Number must be unique)\n");
        scanf("%d", &inputPPS);
        if (checkUnique(head_ptr, inputPPS) == 1) {

            newNode->surveyDetails.ppsNo = inputPPS;
            printf("\nPlease enter your first name:");
            scanf("%s", newNode->surveyDetails.fName);
            printf("\nPlease enter your last name:");
            scanf("%s", newNode->surveyDetails.lName);
            //printf("\nEnter email address: ");
            //do email validation
            //scanf("%s", newNode->studentData.email);

            printf("\nEnter current address: ");
            scanf(" %s", newNode->surveyDetails.address);//takes in the next 99 characters until a newline is found

            printf("\nPlease enter your :");
            scanf("%d", &newNode->surveyDetails.age);
            printf("\nPlease enter your yearly salary (as whole number):");
            scanf("%d", &newNode->surveyDetails.income);
            printf("\nHow many cigarrettes do you smoke a day? :");
            scanf("%d", &newNode->surveyDetails.ciggiesSmoked);
            printf("\nHow many units of alcohol do you drink in a day? :");
            scanf("%d", &newNode->surveyDetails.unitsTaken);
            printf("\nHow many time do you exercise every week? :");
            scanf("%d", &newNode->surveyDetails.timesExercised);


            while (temp != NULL)
            {
                if (sortedInsert(&head_ptr, newNode) == 1) {
                    printf("\nSurvey stored successfully\n");
                    break;
                }
                temp = temp->next;

            }

            //printf("\nSurvey didnt work successfully\n");


            //do sorted insert
        }
        else {//if pps is not unique recursively start function again prompting user
            printf("\nWe still value your feedback on this topic! If you believe you have entered your PPS incorrectly you can now try again!");
            addElement(head_ptr);
        }

    }
}

void addElement_AtStart(struct listelement** head_ptr)
{

    struct listelement *newNode;
    int inputPPS;

    newNode = (struct listelement*)malloc(sizeof(struct listelement));

    printf("\nWe will now take details from you for the survery...\n");
    printf("\nPlease enter your PPS number (Number must be unique)\n");
    scanf("%d", &inputPPS);
    if (checkUnique(head_ptr, inputPPS) == 1) {
        newNode->surveyDetails.ppsNo = inputPPS;
        //do unique check
        printf("\nPlease enter your first name:");
        scanf("%s", newNode->surveyDetails.fName);
        printf("\nPlease enter your last name:");
        scanf("%s", newNode->surveyDetails.lName);
        printf("\nEnter email address: ");
        //do email validation
        //scanf("%s", newNode->studentData.email);

        printf("\nEnter current address: ");
        scanf(" %s", newNode->surveyDetails.address);//takes in the next 99 characters until a newline is found

        printf("\nPlease enter your age:");
        scanf("%d", &newNode->surveyDetails.age);
        printf("\nPlease enter your yearly salary (as whole number):");
        scanf("%d", &newNode->surveyDetails.income);
        printf("\nHow many cigarrettes do you smoke a day? :");
        scanf("%d", &newNode->surveyDetails.ciggiesSmoked);
        printf("\nHow many units of alcohol do you drink in a day? :");
        scanf("%d", &newNode->surveyDetails.unitsTaken);
        printf("\nHow many time do you exercise every week? :");
        scanf("%d", &newNode->surveyDetails.timesExercised);
    }
    else {//if pps is not unique recursively start function again prompting user
        printf("\nWe still value your feedback on this topic! If you believe you have entered your PPS incorrectly you can now try again!");
        addElement_AtStart(head_ptr);
    }


    //no sorted insert if file has surveys sorting will be done in addElement

    newNode->next = *head_ptr;

    *head_ptr = newNode; // transfer the address of newNode' to'head'

}
int sortedInsert(struct listelement** head_ref, struct listelement* newNode)
{
    struct listelement* temp;
    /* Special case for the head end */
    if (*head_ref == NULL || (*head_ref)->surveyDetails.ppsNo >= newNode->surveyDetails.ppsNo)
    {
        newNode->next = *head_ref;
        *head_ref = newNode;
        printf("At head");
        return 1;
    }
    else
    {
        /* Locate the node before the point of insertion */
        temp = *head_ref;
        while (temp->next != NULL &&
            temp->next->surveyDetails.ppsNo < newNode->surveyDetails.ppsNo)
        {
            temp = temp->next;
        }
        newNode->next = temp->next;
        temp->next = newNode;
        return 1;
    }
    printf("failed");
}
int checkUnique(struct listelement *head_ptr, int inputPPS) {
    int nodeNum = 0;
    struct listelement *temp;
    temp = head_ptr;



    while (temp != NULL)
    {
        if (nodesAdded == 0) {
            nodesAdded++;
            printf("\n First node so is unique");
            return 1;
        }
        if (temp->surveyDetails.ppsNo== inputPPS )
        {
            printf("\n There is a user in the survey system with this PPS Number.");
            return 0;
        }
        nodeNum++;
        temp = temp->next;
    }
    printf("\nPPS Number is unique. Continuing...\n We will now ask you for your survey details... ");

    nodesAdded++;
    return 1;

}

编辑: 到目前为止修改过的代码,目前我遇到了一个问题,即变量被输入但是节点没有正确分配为头节点,这是在调试中发现的,在添加第二个元素 head_ptr 时会有奇怪的值(不是输入的)。

void addElement(struct listelement** head_ptr)
{
    int data;
    int inputPPS;
    struct listelement *temp;
    struct listelement *newNode;



    if (*head_ptr == NULL)
    {

        addElement_AtStart(head_ptr);

    }

    else

    {

        temp = *head_ptr;
        newNode = (struct listelement*)malloc(sizeof(struct listelement));

        printf("\nPlease enter your PPS number (Number must be unique)\n");
        scanf("%d", &inputPPS);
        if (checkUnique(&head_ptr, inputPPS) == 1) {

            newNode->surveyDetails.ppsNo = inputPPS;
            printf("\nPlease enter your first name:");
            scanf("%s", newNode->surveyDetails.fName);
            printf("\nPlease enter your last name:");
            scanf("%s", newNode->surveyDetails.lName);
            //printf("\nEnter email address: ");
            //do email validation
            //scanf("%s", newNode->studentData.email);

            printf("\nEnter current address: ");
            scanf(" %s", newNode->surveyDetails.address);//takes in the next 99 characters until a newline is found

            printf("\nPlease enter your :");
            scanf("%d", &newNode->surveyDetails.age);
            printf("\nPlease enter your yearly salary (as whole number):");
            scanf("%d", &newNode->surveyDetails.income);
            printf("\nHow many cigarrettes do you smoke a day? :");
            scanf("%d", &newNode->surveyDetails.ciggiesSmoked);
            printf("\nHow many units of alcohol do you drink in a day? :");
            scanf("%d", &newNode->surveyDetails.unitsTaken);
            printf("\nHow many time do you exercise every week? :");
            scanf("%d", &newNode->surveyDetails.timesExercised);


            while (temp != NULL)
            {
                if (sortedInsert(head_ptr, newNode) == 1) {
                    printf("\nSurvey stored successfully\n");
                    break;
                }
                temp = temp->next;

            }

            //printf("\nSurvey didnt work successfully\n");


            //do sorted insert

        }
        else if (checkUnique(&head_ptr, inputPPS) == 0){//if pps is not unique recursively start function again prompting user
            printf("\nWe still value your feedback on this topic! If you believe you have entered your PPS incorrectly you can now try again!");
            free(newNode);
        }

    }
}

void addElement_AtStart(struct listelement** head_ptr)
{

    struct listelement *newNode;
    int inputPPS;

    newNode = (struct listelement*)malloc(sizeof(struct listelement));

    printf("\nWe will now take details from you for the survery...\n");
    printf("\nPlease enter your PPS number (Number must be unique)\n");
    scanf("%d", &inputPPS);
    if (checkUnique(head_ptr, inputPPS) == 1) {
        newNode->surveyDetails.ppsNo = inputPPS;
        //do unique check
        printf("\nPlease enter your first name:");
        scanf("%s", newNode->surveyDetails.fName);
        printf("\nPlease enter your last name:");
        scanf("%s", newNode->surveyDetails.lName);
        printf("\nEnter email address: ");
        //do email validation
        //scanf("%s", newNode->studentData.email);

        printf("\nEnter current address: ");
        scanf(" %s", newNode->surveyDetails.address);//takes in the next 99 characters until a newline is found

        printf("\nPlease enter your age:");
        scanf("%d", &newNode->surveyDetails.age);
        printf("\nPlease enter your yearly salary (as whole number):");
        scanf("%d", &newNode->surveyDetails.income);
        printf("\nHow many cigarrettes do you smoke a day? :");
        scanf("%d", &newNode->surveyDetails.ciggiesSmoked);
        printf("\nHow many units of alcohol do you drink in a day? :");
        scanf("%d", &newNode->surveyDetails.unitsTaken);
        printf("\nHow many time do you exercise every week? :");
        scanf("%d", &newNode->surveyDetails.timesExercised);
    }
    else {//if pps is not unique recursively start function again prompting user

        printf("\nWe still value your feedback on this topic! If you believe you have entered your PPS incorrectly you can now try again!");
        free(newNode);

    }


    //no sorted insert if file has surveys sorting will be done in addElement

    newNode->next = *head_ptr;

    *head_ptr = newNode; // transfer the address of newNode' to'head'


    free(newNode);
}
int sortedInsert(struct listelement** head_ref, struct listelement* newNode)
{
    struct listelement* temp;
    /* Special case for the head end */
    if (*head_ref == NULL || (*head_ref)->surveyDetails.ppsNo >= newNode->surveyDetails.ppsNo)
    {
        newNode->next = *head_ref;
        *head_ref = newNode;
        printf("At head");
        return 1;
    }
    else
    {
        /* Locate the node before the point of insertion */
        temp = *head_ref;
        while (temp->next != NULL &&
            temp->next->surveyDetails.ppsNo < newNode->surveyDetails.ppsNo)
        {
            temp = temp->next;
        }
        newNode->next = temp->next;
        temp->next = newNode;
        return 1;
    }
    printf("failed");
}
int checkUnique(struct listelement *head_ptr, int inputPPS) {
    int nodeNum = 0;
    struct listelement *temp;
    temp = head_ptr;



    while (temp != NULL)
    {
        if (nodesAdded == 0) {
            nodesAdded++;
            printf("\n First node so is unique");
            return 1;
        }
        if (temp->surveyDetails.ppsNo== inputPPS )
        {
            printf("\n There is a user in the survey system with this PPS Number.");
            return 0;
        }
        nodeNum++;
        temp = temp->next;
    }
    printf("\nPPS Number is unique. Continuing...\n We will now ask you for your survey details... ");

    nodesAdded++;
    return 1;

}

【问题讨论】:

  • 您的整个while (temp-&gt;next...)... if (sortedInsert...break... temp-&gt;next= newNode 有异味。再复习一下逻辑。

标签: c list sorting linked-list


【解决方案1】:

addElement 调用sortedInsertnewNode 插入到排序位置,但随后在temp 返回后重新插入newNode。所以,该节点总是在第一个节点之后立即插入,并且之前插入的任何一个节点仍然指向它,因此列表将无限循环。

如果checkUnique 失败,您的代码也会在addElement 中泄漏内存,并且出于同样的原因会在addElement_AtStart 中插入一个垃圾节点。您在将第一个元素插入列表的情况下进行了不必要的特殊处理,并且复制了所有提出问题的代码;这是一件非常糟糕的事情。此外,checkUnique 修改全局状态 (nodesAdded),即使调用代码可能决定不实际插入节点。

编辑:我过去曾被要求提供工作代码而不是回答问题。我相信我上面给出的建议确实解决了这个问题,但是还有其他问题导致它仍然失败。我创建了一个简单的工作示例here,所以只有当你真的想看的时候才能看它……如果你看它,请仔细研究它,看看特殊和重复的情况是如何被消除的。

【讨论】:

  • 你能解释一下你所说的垃圾节点是什么意思吗?我已经删除了重新插入我相信的 newNode 的代码,但是我遇到了同样的错误。
  • addElement_AtStart 分配一个新节点,然后请求 pps,如果 checkUnique 没有返回 1,它会再次调用 addElement_AtStart。一旦返回,它会将未初始化的newNode 插入到列表中。
  • 我尝试在 else 子句中添加 free(temp) 以检查唯一性,但它没有提供解决方案。有没有一种特殊的方式我应该取消分配节点?
  • 只有在checkUnique 失败时才会发生垃圾条目/内存泄漏,如果您输入唯一的 pps 值,则不会发生这种情况。我只是指出这是一个额外的问题,不一定会导致您的直接问题。你能发布你更新的代码吗?
  • 有一些改动的代码现已上线。当我将第一个节点分配给列表时,它不接受使用断点的值,它只会到达出现问题的函数的末尾。目前我正试图让 checkUnique 失败,因为我想确保没有重复项,所以目前我一直在使用相同的 pps 进行调查以测试 @pat
猜你喜欢
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 2014-04-01
  • 2012-06-26
  • 2017-12-05
  • 2014-06-07
  • 2012-08-02
  • 2012-10-07
相关资源
最近更新 更多