lucky_789 发表于 2015-2-4 13:55:41

学习Nisy的C教程第30课后写的通讯录程序,欢迎来查错

学习Nisy的C教程第30课后,写了个通讯录程序,用tc2编译成功,运行时末尾有一行提示:
Null pointer assignment
改用vc6编译,运行正常。不知问题出在哪里,请大家帮忙分析分析,谢谢。
(感谢扎西,现已添加了一些注释)
/* list3.h -- 通讯录头文件                  */
/* 本通讯录的联系人姓名和手机号码串可任意长度 */

#define NULL 0


typedef struct
{
        char *name;        /* 联系人姓名 */
        char *phone;        /* 手机号码 */
}Contacts;

#define ElementType Contacts

/* #define ElementType char */

typedef struct
{
        ElementType *pbuffer;
        int nlen;        /* 当前联系人数量 */
        int nmax;        /* 联系人数量上限 */
}List;

/* 初始化 */
List * InitList(int n);

/* 清除通讯录 */
int DestroyList(List * lp);

/* 追加联系人 */
int AppendList(List * lp, ElementType *data);

/* 插入联系人 */
int InsertList(List * lp, ElementType *data, int n);

/* 删除联系人 */
int DeleteList(List * lp, int n);

/* 遍历联系人 */
int TraverseList(List * lp, void (*f)(ElementType *pdata));

/* 读取一个联系人 */
int GetElement(List * lp, ElementType *pdata, int n);

/* list3.c -- 通讯录文件                      */
/* 本通讯录的联系人姓名和手机号码串可任意长度 */

#include"List3.h"

/* 初始化通讯录 */
List * InitList(int n)
{
        List * lp = NULL;
        lp = (List *)malloc(sizeof(List));
        if(!lp)
        {
                return lp;
        }
        lp->pbuffer = (ElementType *)malloc(sizeof(ElementType) * n);
        if (!lp->pbuffer)
        {
                free(lp);
                lp = NULL;
                return lp;
        }
        lp->nmax = n;
        lp->nlen = 0;
        return lp;
}

/* 清除通讯录 */
int DestroyList(List * lp)
{
        int i;
        if (lp)
        {
                for (i = 0; i < lp->nlen; i++)
                {
                        if (lp->pbuffer.name) free(lp->pbuffer.name);
                        if (lp->pbuffer.phone) free(lp->pbuffer.phone);
                }
                /* if (lp->pbuffer) free(lp->pbuffer); */
                if (lp) free(lp);
        }
        return 1;
}

/* 追加联系人 */
int AppendList(List * lp, ElementType *pdata)
{
        int nlen;
        if (lp->nlen >= lp->nmax)
        {
                printf("\nList is already full!\n");
                return 0;
        }

        /* 每个联系人单独申请空间,这样联系人姓名和手机号就可以不限定长度了 */
        nlen = strlen(pdata->name);
        lp->pbuffer.name = (char *)malloc(nlen + 1);
        if (!(lp->pbuffer.name))
        {
                return 0;
        }
        memset(lp->pbuffer.name, 0, nlen + 1);

        nlen = strlen(pdata->phone);
        lp->pbuffer.phone = (char *)malloc(nlen + 1);
        if (!(lp->pbuffer.phone))
        {
                free(lp->pbuffer.name);
                return 0;
        }
        memset(lp->pbuffer.phone, 0, nlen + 1);

        /* 不是引用地址而是复制姓名和手机号,便于循环动态追加 */
        strcpy(lp->pbuffer.name, pdata->name);
        strcpy(lp->pbuffer.phone, pdata->phone);

        lp->nlen++;
        return lp->nlen;
}

/* 插入联系人 n=1,2,3,...*/
int InsertList(List * lp, ElementType *pdata, int n)
{
        int i;
        int nlen;
        if (lp->nlen >= lp->nmax)
        {
                printf("\nList is already full!\n");
                return 0;
        }
        if (n <= 0 || n > lp->nlen)
        {
                printf("\nThe position to insert is out of List!\n");
                return 0;
        }
        for (i = lp->nlen; i >= n; i--)
        {
                memcpy(&lp->pbuffer, &lp->pbuffer, sizeof(ElementType));
        }

        /* memcpy(&lp->pbuffer, pdata, sizeof(ElementType)); */
        /* 每个联系人单独申请空间,这样联系人姓名和手机号就可以不限定长度了 */
        nlen = strlen(pdata->name);
        lp->pbuffer.name = (char *)malloc(nlen + 1);
        if (!(lp->pbuffer.name))
        {
                return 0;
        }
        memset(lp->pbuffer.name, 0, nlen + 1);

        nlen = strlen(pdata->phone);
        lp->pbuffer.phone = (char *)malloc(nlen + 1);
        if (!(lp->pbuffer.phone))
        {
                free(lp->pbuffer.name);
                return 0;
        }
        memset(lp->pbuffer.phone, 0, nlen + 1);

        /* 不是引用地址而是复制姓名和手机号,便于循环动态插入 */
        strcpy(lp->pbuffer.name, pdata->name);
        strcpy(lp->pbuffer.phone, pdata->phone);
        lp->nlen++;

        return lp->nlen;
}

/* 删除联系人n=1,2,3,...*/
int DeleteList(List * lp, int n)
{
        int i;
        if (lp->nlen <= 0)
        {
                printf("\nYou can't delete because List is Empty!\n");
                return 0;
        }
        if (n <= 0 || n > lp->nlen)
        {
                printf("\nThe position to delete is out of List!\n");
                return 0;
        }

        /* 先释放该联系人占用的内存 */
        if(lp->pbuffer.name) free(lp->pbuffer.name);
        if(lp->pbuffer.phone) free(lp->pbuffer.phone);

        /* 再将其后的联系人信息的指针逐个往前复制 */
        for (i = n - 1; i < lp->nlen; i++)
        {
                memcpy(&lp->pbuffer, &lp->pbuffer, sizeof(ElementType));
        }

        /* 原末尾的联系人姓名、手机号处的指针清除 */
        lp->pbuffer.name = NULL;
        lp->pbuffer.phone = NULL;
        /* memset(&lp->pbuffer, 0, sizeof(ElementType)); */

        lp->nlen--;
        return lp->nlen;
}

/* 遍历联系人 */
int TraverseList(List * lp, void (*f)(ElementType *pdata))
{
        int i;
        if (lp->nlen == 0)
        {
                printf("\nList is Empty!\n");
                return 0;
        }
        for (i = 0; i < lp->nlen; i++)
        {
                f(&lp->pbuffer);
        }
        printf("\n");
        return 1;
}

/* 读取一条联系人记录n=1,2,3,... */
int GetElement(List * lp, ElementType *pdata, int n)
{
        if (n <= 0 || n > lp->nlen)
        {
                printf("\nThe position to delete is out of List!\n");
                return 0;
        }
        memcpy(pdata, &lp->pbuffer, sizeof(ElementType));
        return 1;
}

/* test3.c -- 通讯录文件                      */
/* 和list3.c一起编译                        */
/* 本通讯录的联系人姓名和手机号码串可任意长度 */

#include "List3.h"

void myprintf(ElementType * pdata)
{
        printf("{%s, %s}\n", pdata->name, pdata->phone);
}

int main()
{
        int i;
        List *lp = InitList(9);
        ElementType str[] = {
                {"AAAAAA","11111111111"},
                {"BBBBBB","22222222222"},
                {"CCCCCC","33333333333"},
                {"DDDDDD","44444444444"},
                {"EEEEEE","55555555555"},
                {"FFFFFF","66666666666"},
                {"GGGGGG","77777777777"},
                {"HHHHHH","88888888888"},
                {"IIIIII","99999999999"},
        };
        ElementType data = {"KKKKKK","12345678901"};
        if(!lp)
        {
                printf("\nInitList error!\n");
                return 0;
        }
        for (i = 0; i < 9; i++)
        {
                AppendList(lp, str+i);
        }
        /* 以上改为运行时循环输入联系人信息。这里为简化示例才固定初始化信息 */


        TraverseList(lp, myprintf);

        /* 以下可改为菜单选择动态追加、插入、删除、检索、清除。*/

        DeleteList(lp, 3);
        TraverseList(lp, myprintf);

        DeleteList(lp, 3);
        TraverseList(lp, myprintf);

        GetElement(lp, &data, 3);
        myprintf(&data);
        printf("\n");

        AppendList(lp, &data);
        TraverseList(lp, myprintf);

        InsertList(lp, &data, 1);
        TraverseList(lp, myprintf);

        AppendList(lp, &data);
        TraverseList(lp, myprintf);

        DestroyList(lp);/* 用tc2编译的运行时这里提示 "Null pointer assignment" ,请找出错在哪里*/

        return 1;
}


漂摆 发表于 2015-2-5 18:51:22

学的好快呀~我才看到第7课~而且菱形代码还没有实现,正在努力思考ing~
页: [1]
查看完整版本: 学习Nisy的C教程第30课后写的通讯录程序,欢迎来查错