c - c 中的链接列表存在问题

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

最佳答案

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

另一种情况是,当已经有某个节点时,您正在遍历到最后一个节点并在那里添加一个节点,但没有要求输入。这就是为什么对于第二个节点及之后的节点,您没有其他详细信息。

else 部分中 malloc 后,您必须像在 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一次,获取输入并填充结构,然后将其添加到列表中的适当位置。这样你就可以省略函数中很大一部分冗余代码。

关于c - c 中的链接列表存在问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21908424/

相关文章:

c - C 中的预处理器指令 : macros using __LINE__

c - print_list 函数只打印链表中用户的第一个输入

python - 在带有嵌套 enumerate() 的 for 循环中添加第二个参数有什么作用?

c - 如何在c中找到行和列之间的分隔空间

c++ - Libjpeg 错误 - 在状态 205 中调用不当

r - ggplot 用于存储在 3D 数组中的对象

java - 如何动态地将谓词添加到列表中

java - 将元素添加到列表时 Android 应用程序崩溃

c - 如何通过网络套接字可移植地发送 C 结构?

计算大写字母和小写字母