在c中遇到链接列表问题

时间:2014-02-20 12:54:24

标签: c list

我遇到一些代码问题我必须添加选项以将人输入到我的结构链接列表中。我可以将这个人添加到第一个节点,并带有一个标识符的整数,但是当我来添加另一个时,它只询问整数而不是其他细节。这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include "linkedlist.h"     /* conatins structure definition */

/*  Function Prototypes 
    Note that variable names have been removed as they are 
    not actually required - they are optional
*/
int fnTotalList(struct listnode *);
struct listnode *fnAddItem(struct listnode *, int);
void fnPrintList(struct listnode *);
int fnMenu(void);
struct listnode *fnRemoveEndItem(struct listnode *, int *);
struct listnode *fnRemoveStartItem(struct listnode *, int *);
void fnSearchList(struct listnode *, int);

int main(int argc, char *argv[])
{
     struct listnode *ptrHead = NULL;
     struct listnode *ptrTemp = NULL;
     int nChoice = 0;
     int nRun = 1;
     int nItem = 0;

     while(nRun)
     {
         nChoice = fnMenu();

         switch(nChoice)
         {
             case 1:    /* Add an item */
                            printf("Please enter an integer : ");
                            scanf("%d", &nItem);
                            ptrHead = fnAddItem(ptrHead,nItem);
                            break;

              case 2:   /* Print the list */
                            fnPrintList(ptrHead);
                            printf("The list total is %d\n", fnTotalList(ptrHead));
                            break;

              case 3:   /* Remove an end item */
                            ptrHead = fnRemoveEndItem(ptrHead, &nItem);
                            if(nItem == -9999)
                                printf("Nothing to remove - empty list\n\n");
                            else
                                printf("The removed value is %d\n\n", nItem);
                            break;

              case 4:   /* Remove a start item */
                            ptrHead = fnRemoveStartItem(ptrHead, &nItem);
                            if(nItem == -9999)
                                printf("Nothing to remove - empty list\n\n");
                            else
                                printf("The removed value is %d\n\n", nItem);
                            break;

              case 5:   /* Search the list */
                            printf("Please enter the search value : ");
                            scanf("%d", &nItem);
                            fnSearchList(ptrHead, nItem);
                            break;

              case 6:   /* Exit program */
                            nRun = 0;   /* set to zero to stop the while loop */
                            break;
        }
    }

    return 0;
}

struct listnode *fnAddItem(struct listnode *ptrH, int nNumber)
{
    struct listnode *ptrTemp = NULL;

    if(ptrH == NULL)
    {
        /* Special case - list empty */
        ptrH = (struct listnode *)malloc(sizeof(struct listnode));
        if(ptrH == NULL)
        {
            printf("Adding to empty list - malloc has failed\n");
            exit(1);
        }
        /* malloc has worked - set values */
        (*ptrH).nVal = nNumber;
        printf("Please Enter First , Second & Last Name : ");
        scanf("%s %s %s",(*ptrH).arcFirstName,(*ptrH).arcMiddleName,(*ptrH).arcLastName);
        printf("Please Enter Sex M or F : ");
        scanf("%s", (*ptrH).cSex);
        printf("DOB - DDMMYYYY\n");
        scanf("%i %i %i", &nD, &nM, &nY);
        (*ptrH).strDOB.nDay=nD;
        (*ptrH).strDOB.nMonth=nM;
        (*ptrH).strDOB.nYear=nY;
        ptrH->ptrNext = NULL;       /* This is important as it signals
                                                the last node within the list */
    }
    else
    {
        /* There are items already in the list
            need to locate the end - use a while loop
            to step through looking for ptrNext to
            equal NULL */

        ptrTemp = ptrH; /* Use a temp pointer */
        while(ptrTemp->ptrNext != NULL)
        {
            /* As ptrNext has a value there is a node
                hanging off it */
            ptrTemp = ptrTemp->ptrNext;
        }
        /* ptrTemp is now pointing at the last node
            within the list
            Now, create a new node that "hangs off"
            ptrNext within this last node  */

            ptrTemp->ptrNext = (struct listnode *)malloc(sizeof(struct listnode));
            if(ptrTemp->ptrNext == NULL)
            {
                printf("Adding to end of list - malloc has failed\n");
                exit(1);
            }
            ptrTemp->ptrNext->nVal = nNumber;
            ptrTemp->ptrNext->ptrNext = NULL;
    }

    return ptrH;    /* This is really only needed when adding the first item
                            to the list - but have to do it in all cases to avoid
                            error messages */
}

int fnMenu(void)
{
     int nChoice;

     printf("Choices menu\n\n");
     printf("1.\tAdd an item\n");
     printf("2.\tPrint list\n");
     printf("3.\tRemove an end item\n");
     printf("4.\tRemove a start item\n");
     printf("5.\tSearch for a value\n");
     printf("6.\tQuit\n\n");
     printf("Please enter a choice :");
     scanf("%d", &nChoice);

     return nChoice;
}

void fnPrintList(struct listnode *ptrH)
{
    if(!ptrH)
    {
        printf("\n\n\tEmpty list\n");
    }
    else
    {
        while(ptrH)
        {
            printf("%d\n", ptrH->nVal);
            ptrH = ptrH->ptrNext;
        }
        printf("\nEnd of list\n\n");
    }

}

struct listnode *fnRemoveEndItem(struct listnode *ptrH, int *ptrNum)
{
    /*  There are two special cases ...
        1. When the list is empty
        2. When there is only one node within the list
    */
    struct listnode *ptrTemp = NULL;

    if(!ptrH)
    {
        /* The list is empty */
        *ptrNum = -9999;        /* A value to signal empty list */
    }
    else if(!ptrH->ptrNext)
    {
        /*  There is only one node in the list
            as ptrNext within the first node
            is NULL
        */
        *ptrNum = ptrH->nVal; 
        free(ptrH);             /*  This releases the memory allocated
                                    by malloc() back to the heap */

        ptrH = NULL;            /*  As this was the last item to remove
                                    need to return NULL so that ptrHead
                                    is set to NULL */
    }
    else
    {
        /*  There are more than one nodes in the list,
            need to step through to find the last but
            one node
        */
        ptrTemp = ptrH;
        while(ptrTemp->ptrNext->ptrNext)
        {
            ptrTemp = ptrTemp->ptrNext;
        }

        /*  ptrTemp is now pointing to the last but
            one node so can delete the last one
        */
        *ptrNum = ptrTemp->ptrNext->nVal;
        free(ptrTemp->ptrNext);
        ptrTemp->ptrNext = NULL;    /* Set to NULL as this is 
                                       now the last node
                                    */
    }

    return ptrH;
}


struct listnode *fnRemoveStartItem(struct listnode *ptrH, int *ptrNum)
{
    struct listnode *ptrTemp = NULL;

    if(!ptrH)
    {
        /*  Empty list */
        *ptrNum = -9999;
        return ptrH;
    }
    else
    {
        ptrTemp = ptrH->ptrNext;
        *ptrNum = ptrH->nVal;
        free(ptrH);
        return ptrTemp;
    }
}


void fnSearchList(struct listnode *ptrH, int nSearchVal)
{
    struct listnode *ptrTemp = ptrH;
    int nCount = 0;

    if(!ptrH)
    {
        /* Empty List */
        printf("\n\nEmpty List \n\n");
    }
    else
    {
        while(ptrTemp->ptrNext)
        {
            if(ptrTemp->nVal == nSearchVal)
            {
                printf("The value %d has been located\n", ptrTemp->nVal);
                nCount++;
            }
            ptrTemp = ptrTemp->ptrNext;
        }

        if(!nCount)
            printf("\t\tValue not found within the list\n");
        else
            printf("\t\tA total of %d were found\n", nCount);
    }   
    printf("The list totals %d\n", fnTotalList(ptrH));
}

int fnTotalList(struct listnode *ptrH)
{
    struct listnode *ptrTemp = ptrH;
    int nTotal = 0;

    if(ptrTemp)
    {
        while(ptrTemp)
        {
            nTotal += ptrTemp->nVal;
            ptrTemp = ptrTemp->ptrNext;
        }
    }

    return nTotal;
}

1 个答案:

答案 0 :(得分:1)

在函数fnAddItem中,有两种情况,一种是当指针为NULL时,即List Empty,并且您正在正确添加第一个节点。

另一个是当已经有一些节点时,你正在遍历最后一个并在那里添加一个节点,但没有要求输入。这就是为什么第二节点以后你没有其他细节。

malloc部分else之后,您必须像if部分那样接受输入。

struct listnode *fnAddItem(struct listnode *ptrH, int nNumber)
{
    struct listnode *ptrTemp = NULL;

    if(ptrH == NULL)
    {
        /* Special case - list empty */
        ptrH = (struct listnode *)malloc(sizeof(struct listnode));
        if(ptrH == NULL)
        {
            printf("Adding to empty list - malloc has failed\n");
            exit(1);
        }
        /* malloc has worked - set values */
        (*ptrH).nVal = nNumber;
        printf("Please Enter First , Second & Last Name : ");
        scanf("%s %s %s",(*ptrH).arcFirstName,(*ptrH).arcMiddleName,(*ptrH).arcLastName);
        printf("Please Enter Sex M or F : ");
        scanf("%s", (*ptrH).cSex);
        printf("DOB - DDMMYYYY\n");
        scanf("%i %i %i", &nD, &nM, &nY);
        (*ptrH).strDOB.nDay=nD;
        (*ptrH).strDOB.nMonth=nM;
        (*ptrH).strDOB.nYear=nY;
        ptrH->ptrNext = NULL;       /* This is important as it signals
                                                the last node within the list */
    }
    else
    {
        /* There are items already in the list
            need to locate the end - use a while loop
            to step through looking for ptrNext to
            equal NULL */

        ptrTemp = ptrH; /* Use a temp pointer */
        while(ptrTemp->ptrNext != NULL)
        {
            /* As ptrNext has a value there is a node
                hanging off it */
            ptrTemp = ptrTemp->ptrNext;
        }
        /* ptrTemp is now pointing at the last node
            within the list
            Now, create a new node that "hangs off"
            ptrNext within this last node  */

            ptrTemp->ptrNext = (struct listnode *)malloc(sizeof(struct listnode));
            if(ptrTemp->ptrNext == NULL)
            {
                printf("Adding to end of list - malloc has failed\n");
                exit(1);
            }
            /* malloc has worked - set values */
        ptrTemp->ptrNext->nVal = nNumber;
        printf("Please Enter First , Second & Last Name : ");
        scanf("%s %s %s",ptrTemp->ptrNext->arcFirstName,ptrTemp->ptrNext->arcMiddleName,ptrTemp->ptrNext->arcLastName);
        printf("Please Enter Sex M or F : ");
        scanf("%s", ptrTemp->ptrNext->cSex);
        printf("DOB - DDMMYYYY\n");
        scanf("%i %i %i", &nD, &nM, &nY);
        ptrTemp->ptrNext->strDOB.nDay=nD;
        ptrTemp->ptrNext->strDOB.nMonth=nM;
        ptrTemp->ptrNext->strDOB.nYear=nY;
        ptrTemp->ptrNext->ptrNext = NULL;       /* This is important as it signals
                                                the last node within the list */  
    }

    return ptrH;    /* This is really only needed when adding the first item
                            to the list - but have to do it in all cases to avoid
                            error messages */
}

这是一个糟糕的设计,您应该malloc一次,接受输入并填充结构,然后将其添加到列表的适当位置。通过这种方式,您可以在函数中省略大部分冗余代码。