黄翼 发表于 2020-2-23 16:28:57

在第二次调用查找函数的时候就出错,能帮我看看吗?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Telbook
{
        char name;
        char number;
        char beizhu;
        struct Telbook *next;
} PLR,*PLRPIN;


void PrintInfo(PLRPIN Info);
void InsertInfo(PLRPIN *Info); //把地址给它,用*把系统分给头指针的地址里的值拿出来做修改,就可以指向其它的值,所以要两层引用
void InputInfo(PLRPIN);
void releaseInfo(PLRPIN *Info);//释放所有内存空间,不是一个结构哟
void searchInfo(PLRPIN Info);
void DelInfo(PLRPIN *Info);
void ModfiyInfo(PLRPIN *INFO);


#define ME_ALLCARD 1
#define ME_FOUNDCARD 2
#define ME_DELCARD 3
#define ME_MODIFYCARD 4
#define ME_NEWCARD 5
#define ME_EXIT 0

#define _CRT_SECURE_NO_WARNINGS //排错

int main()
{
        int iMenu;
        char cExit,cInput;
        PLRPIN Headr=NULL; //声明一个头指针,并给值等0;

       
        do
        {
                printf("\n|-------------------------------|菜单|-----------------------------------|\n\n");
                printf("|1.显示所有名片|2.查找名片|3.删除名片|4.修改名片|5.新建名片|0.退出|\n\n");
                printf("|--------------------------------------------------------------------------|\n");

                printf("\n请输入数字选择菜单:");
reInput:
                scanf("%d",&iMenu); //条件选择菜单
                switch(iMenu)
                {
                case ME_ALLCARD:
                        PrintInfo(Headr);
                        break;
                case ME_FOUNDCARD:
               
                        searchInfo(Headr);
                        break;
                case ME_DELCARD:
                        DelInfo(&Headr);
                        break;
                case ME_NEWCARD:
                        while(1)
                        {
                                printf("请问是否要新建名片(Y/N):");
                                do
                                {
                                        cInput=getchar();

                                }while(cInput !='Y' && cInput != 'N');
                                if(cInput == 'Y')
                                {
                                        InsertInfo(&Headr);
                                }
                                else
                                {
                                        break;
                                }
                        }
                       
                        break;
                case ME_MODIFYCARD:
                        ModfiyInfo(&Headr);
                        break;
                case ME_EXIT:
                        printf("感谢您的使用,程序准备退出!\n确认退出请输入(Y/N):");
                        do
                        {
                        cExit=getchar();
                        }while(cExit != 'Y' && cExit != 'N');
                        if(cExit == 'Y')
                        {
                                releaseInfo(&Headr);
                                exit(1);
                        }
                        break;
                default :
                        printf("输入的选项无效,请重新输入(1~5):");
                        goto reInput;
                        break;
                }
        }while(1);
        //releaseInfo(&Headr);
        return 0;
}


void DelInfo(PLRPIN *Info) //删除信息
{
        char cName;
        char cYesNo;
        PLRPIN Current,Previous;

        printf("请输入要删除的名片姓名:");
        scanf("%s",cName);
        printf("确定要删除 %s 吗?(Y/N):",cName);
        do
        {
               
                cYesNo = getchar();
        }while (cYesNo != 'Y' && cYesNo != 'N');
       
        if(cYesNo == 'Y')
        {
                Current = *Info;
                Previous = NULL;

                while(Current != NULL && Current->name == cName) //搜查符合的条件
                {
                        Previous =Current;
                        Current=Current->next;
                }
                if(Current == NULL)
                {
                        printf("没有找到要删除的名片,请确认您的输入!\n");
                        return ;
                }
                else
                {
                        if(Previous == NULL)
                        {
                                *Info=Current->next;

                        }
                        else
                        {
                                Previous->next=Current->next;
                        }
                        printf("删除成功!\n");
                       free(Current);
                }
        }
}

void InsertInfo(PLRPIN *Info) //传入指向指针结构的指针来修改指针/拿到头指指针就能操作单链表,所有主函数里的是头指针,传递给其它函数便于操作。
{
        PLRPIN Temp,New;
        static PLRPIN Nup; //尾插法的重点,必须是静态变量,才能一直指向NULL
        New=(PLRPIN)malloc(sizeof(PLR));

        if(NULL == New)
        {
                printf("新的空间分配失败\n");
                return ;
        }

        InputInfo(New);
        //--------------------尾插法---------------------------------
        if(*Info != NULL)
        {
                Nup->next = New;
                New->next=NULL;

                /*------------遍历效率代------------------
                while (Temp->next != NULL)
                {
                        //Temp = Temp->next; //搜查NULL
                }
                //找到NULL插入数据
                Temp->next= New;
                New->next = NULL;
                ---------------------------*/
        }
        else
        {
                *Info = New;
                New->next = NULL;
        }
                Nup=New;
        /**************************头插法*********************************
        if(*Info != NULL)
        {
                Temp=*Info; //把头指针放入TEMP 再把新的转接赋值达到插入的目的。
                *Info=New;
                New->next=Temp;
        }
        else
        {
                *Info=New;
                New->next=NULL;
        }
        *******************************************************************/
}

void InputInfo(PLRPIN Info) //输入信息
{
        PLRPIN New;
        New=Info;
        printf("请输入姓名:");
        scanf("%s",New->name);
        printf("请给人物职业:");
        scanf("%s",New->beizhu);
        printf("请输入号码:");
        scanf("%s",New->number);
}

void PrintInfo(PLRPIN Info) //打印输出
{
       
        PLRPIN New;
        int count =1;

        New=Info;

        printf("\n\n|------------------------------|通迅录|----------------------------------|\n\n");
        printf("|编号|\t|姓名|\t|职业|\t|联系方式|\n");
        while(New != NULL )
        {
                printf("%5d%17s%18s%21s\n",count,New->name,New->beizhu,New->number);
                New=New->next;
                count++;
        }
        putchar('\n');
}

void releaseInfo(PLRPIN *Info) //释放空间
{
        PLRPIN Temp;
        while (*Info != NULL)
        {
                Temp=*Info;
                *Info=(*Info)->next;
                free(Temp);
        }
}

void searchInfo(PLRPIN Info)//查找信息
{
        char target;
        PLRPIN New;
        printf("请输入要找查名片的信息[姓名,职业,电话号码] :");
        scanf("%s",target);

        New=Info;

        while(New != NULL)
        {
                if(!strcmp(New->name,target) || !strcmp(New->beizhu,target) || !strcmp(New->number,target))
                {
                        break;
                }
                New = New->next;
        }


        if(New == NULL)
        {
                printf("很抱赚,没有找到您要的结果!\n");
        }
        else
        {
                do
                {
                        printf("已找到符合条件的名片...\n");
                        PrintInfo(New);
                }while(New->next != NULL);               
        }

        releaseInfo(&New);
       
}


void ModfiyInfo(PLRPIN *Info)//修改信息
{
        char cName;
        char cYesNo;
        PLRPIN Current;

        printf("请输入要修改名片的姓名:");
        scanf("%s",cName);
        printf("确定要修改 %s 信息吗?(Y/N):",cName);

        do
        {
                cYesNo = getchar();
        }while (cYesNo != 'Y' && cYesNo != 'N');
       
        if(cYesNo == 'Y')
        {
                Current = *Info;
               

                while(Current != NULL && Current->name == cName) //搜查符合的条件
                {
                        Current=Current->next;
                }
                if(Current == NULL)
                {
                        printf("没有找到要修改的名片,请确认您的输入!\n");
                        return ;
                }
                else
                {
                        printf("找到匹配:%s %s %s\n",Current->name,Current->beizhu,Current->number );
                        printf("将%s修改为:",Current->name);
                        scanf("%s",Current->name);

                        printf("将%s修改为:",Current->beizhu);
                        scanf("%s",Current->beizhu);

                        printf("将%s修改为:",Current->number);
                        scanf("%s",Current->number);
                        printf("修改后的信息为:%s %s %s\n",Current->name,Current->beizhu,Current->number );
                        printf("修改成功!\n");
                }
        }
}


第二次调用查找函数就出错,但不知道是什么原因。

4goodworld 发表于 2020-2-23 22:14:36

本帖最后由 4goodworld 于 2020-2-23 22:15 编辑

个人探讨,你这个检索,为啥要循环呢?
do
                {
                        printf("已找到符合条件的名片...\n");
                        PrintInfo(New);
                }while(New->next != NULL);      
你这个打印函数为啥要循环打印呢?找到了一个,不应该打印一个?
    while(New != NULL )
      {
                printf("%5d%17s%18s%21s\n",count,New->name,New->beizhu,New->number);
                New=New->next;
                count++;
      }

黄翼 发表于 2020-2-23 23:34:14

4goodworld 发表于 2020-2-23 22:14
个人探讨,你这个检索,为啥要循环呢?

你这个打印函数为啥要循环打印呢?找到了一个,不应该打印一个? ...

因为有可能会找到两个,必如我输入职业:有3个是职业是一样的就可以全打出来,还有就是显示所有的时候

黄翼 发表于 2020-2-23 23:36:04

4goodworld 发表于 2020-2-23 22:14
个人探讨,你这个检索,为啥要循环呢?

你这个打印函数为啥要循环打印呢?找到了一个,不应该打印一个? ...

您帮我测试一下,第二次调用查找函数就出错什么原因呢?

4goodworld 发表于 2020-2-23 23:54:22

黄翼 发表于 2020-2-23 23:34
因为有可能会找到两个,必如我输入职业:有3个是职业是一样的就可以全打出来,还有就是显示所有的时候

我个人的建议,你得把自己的函数构思好、设计好,很多东西杂在一起,反而前后制约,让你顾此失彼。
如果打印只打印一个
然后,是不是就可以在搜索里优化,继续搜下去然后继续打印

major_lyu 发表于 2020-2-25 16:08:41

帮你修改了。
主要是DelInfo()和searcheInfo();详细看注释。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Telbook
{
    char name;
    char number;
    char beizhu;
    struct Telbook *next;
} PLR, *PLRPIN;

void PrintInfo(PLRPIN Info);
void InsertInfo(PLRPIN *Info); //把地址给它,用*把系统分给头指针的地址里的值拿出来做修改,就可以指向其它的值,所以要两层引用
void InputInfo(PLRPIN);
void releaseInfo(PLRPIN *Info); //释放所有内存空间,不是一个结构哟
void searchInfo(PLRPIN Info);
void DelInfo(PLRPIN *Info);
void ModfiyInfo(PLRPIN *INFO);

#define ME_ALLCARD 1
#define ME_FOUNDCARD 2
#define ME_DELCARD 3
#define ME_MODIFYCARD 4
#define ME_NEWCARD 5
#define ME_EXIT 0

#define _CRT_SECURE_NO_WARNINGS //排错

int main()
{
    int iMenu;
    char cExit, cInput;
    PLRPIN Headr = NULL; //声明一个头指针,并给值等0;

    do
    {
      printf("\n|-------------------------------|菜单|-----------------------------------|\n\n");
      printf("|1.显示所有名片|2.查找名片|3.删除名片|4.修改名片|5.新建名片|0.退出|\n\n");
      printf("|--------------------------------------------------------------------------|\n");

      printf("\n请输入数字选择菜单:");
    reInput:
      scanf("%d", &iMenu); //条件选择菜单
      switch (iMenu)
      {
      case ME_ALLCARD:
            PrintInfo(Headr);
            break;
      case ME_FOUNDCARD:
            searchInfo(Headr);
            break;
      case ME_DELCARD:
            DelInfo(&Headr);
            break;
      case ME_NEWCARD:
            while (1)
            {
                printf("请问是否要新建名片(Y/N):");
                do
                {
                  cInput = getchar();

                } while (cInput != 'Y' && cInput != 'N');
                if (cInput == 'Y')
                {
                  InsertInfo(&Headr);
                }
                else
                {
                  break;
                }
            }
            break;
      case ME_MODIFYCARD:
            ModfiyInfo(&Headr);
            break;
      case ME_EXIT:
            printf("感谢您的使用,程序准备退出!\n确认退出请输入(Y/N):");
            do
            {
                cExit = getchar();
            } while (cExit != 'Y' && cExit != 'N');
            if (cExit == 'Y')
            {
                releaseInfo(&Headr);
                exit(1);
            }
            break;
      default:
            printf("输入的选项无效,请重新输入(1~5):");
            goto reInput;
            break;
      }
    } while (1);
    //releaseInfo(&Headr);
    return 0;
}

void DelInfo(PLRPIN *Info) //删除信息
{
    char cName;
    char cYesNo;
    PLRPIN Current, Previous;

    printf("请输入要删除的名片姓名:");
    scanf("%s", cName);
    printf("确定要删除 %s 吗?(Y/N):", cName);
    do
    {
      cYesNo = getchar();
    } while (cYesNo != 'Y' && cYesNo != 'N');

    if (cYesNo == 'Y')
    {
      Current = *Info;
      Previous = NULL;
      //while (Current != NULL && Current->name == cName) //这里逻辑错误;应该是Current->name!=name
      while (Current != NULL && strcmp(Current->name, cName))
      {
            Previous = Current;
            Current = Current->next;
      }

      if (Current == NULL)
      {
            printf("没有找到要删除的名片,请确认您的输入!\n");
            return;
      }
      else
      {
            if (Previous == NULL)
            {
                *Info = Current->next;
            }
            else
            {
                Previous->next = Current->next;
            }
            printf("删除成功!\n");
            free(Current);
      }
    }
}

void InsertInfo(PLRPIN *Info) //传入指向指针结构的指针来修改指针/拿到头指指针就能操作单链表,所有主函数里的是头指针,传递给其它函数便于操作。
{
    PLRPIN Temp, New;
    static PLRPIN Nup; //尾插法的重点,必须是静态变量,才能一直指向NULL
    New = (PLRPIN)malloc(sizeof(PLR));

    if (NULL == New)
    {
      printf("新的空间分配失败\n");
      return;
    }

    InputInfo(New);
    //--------------------尾插法---------------------------------
    if (*Info != NULL)
    {
      Nup->next = New;
      New->next = NULL;

      /*------------遍历效率代------------------
                while (Temp->next != NULL)
                {
                        //Temp = Temp->next; //搜查NULL
                }
                //找到NULL插入数据
                Temp->next= New;
                New->next = NULL;
                ---------------------------*/
    }
    else
    {
      *Info = New;
      New->next = NULL;
    }
    Nup = New;
    /**************************头插法*********************************
      if(*Info != NULL)
      {
                Temp=*Info; //把头指针放入TEMP 再把新的转接赋值达到插入的目的。
                *Info=New;
                New->next=Temp;
      }
      else
      {
                *Info=New;
                New->next=NULL;
      }
      *******************************************************************/
}

void InputInfo(PLRPIN Info) //输入信息
{
    PLRPIN New;
    New = Info;
    printf("请输入姓名:");
    scanf("%s", New->name);
    printf("请给人物职业:");
    scanf("%s", New->beizhu);
    printf("请输入号码:");
    scanf("%s", New->number);
}

void PrintInfo(PLRPIN Info) //打印输出
{

    PLRPIN New;
    int count = 1;

    New = Info;

    printf("\n\n|------------------------------|通迅录|----------------------------------|\n\n");
    printf("|编号|\t|姓名|\t|职业|\t|联系方式|\n");
    while (New != NULL)
    {
      printf("%5d%17s%18s%21s\n", count, New->name, New->beizhu, New->number);
      New = New->next;
      count++;
    }
    putchar('\n');
}

void releaseInfo(PLRPIN *Info) //释放空间
{
    PLRPIN Temp;
    while (*Info != NULL)
    {
      Temp = *Info;
      *Info = (*Info)->next;
      free(Temp);
    }
}

void searchInfo(PLRPIN Info) //查找信息
{
    char target;
    PLRPIN New;
    printf("请输入要找查名片的信息[姓名,职业,电话号码] :");
    scanf("%s", target);

    New = Info;
    PLRPIN founded=NULL;
   
    // while (New != NULL)
    // {
    //   if (!strcmp(New->name, target) || !strcmp(New->beizhu, target) || !strcmp(New->number, target))
    //   {
    //         break;
    //   }
    //   New = New->next;
    // } //这一块有问题,只找到第一个符号条件的名片。

    while (New != NULL) // 查找目标名片,把所有找到的名片用新链表founded指示
    {
      if (!strcmp(New->name, target) || !strcmp(New->beizhu, target) || !strcmp(New->number, target))
      {
            PLRPIN node= (PLRPIN)malloc(sizeof(PLR)); // 新建结点存储搜索到的结点
            *node = *New; //将找到的名片内容copy到新链表中
            node->next = NULL; //next 复位,防止影响原链表内容
            if (founded == NULL)
            {
                founded = node;
            }
            else
            {
                founded->next = node;
            }
      }
      New = New->next;
    }

    if (founded == NULL)
    {
      printf("很抱赚,没有找到您要的结果!\n");
    }
    else
    {
      printf("已找到符合条件的名片...\n");
      PrintInfo(founded); // 打印搜索处理的名片
      // do
      // {
      //   printf("已找到符合条件的名片...\n");
      //   //PrintInfo(New);//这个函数是从New所指的结点打印之后的所有名片啊!这样调用有问题吧;

      // } while (New->next != NULL);
    }
    releaseInfo(&founded); // 打印完成后释放掉新建的链表

    //releaseInfo(&New); //不能调用releaseInfo; New所指向的名片结点和Info中的某些结点是共用的。
                         //调用之后,会把Info中与指针New地址相同的结点之后的所有结点的内存空间释放掉
}

void ModfiyInfo(PLRPIN *Info) //修改信息
{
    char cName;
    char cYesNo;
    PLRPIN Current;

    printf("请输入要修改名片的姓名:");
    scanf("%s", cName);
    printf("确定要修改 %s 信息吗?(Y/N):", cName);

    do
    {
      cYesNo = getchar();
    } while (cYesNo != 'Y' && cYesNo != 'N');

    if (cYesNo == 'Y')
    {
      Current = *Info;

      while (Current != NULL && Current->name == cName) //搜查符合的条件
      {
            Current = Current->next;
      }
      if (Current == NULL)
      {
            printf("没有找到要修改的名片,请确认您的输入!\n");
            return;
      }
      else
      {
            printf("找到匹配:%s %s %s\n", Current->name, Current->beizhu, Current->number);
            printf("将%s修改为:", Current->name);
            scanf("%s", Current->name);

            printf("将%s修改为:", Current->beizhu);
            scanf("%s", Current->beizhu);

            printf("将%s修改为:", Current->number);
            scanf("%s", Current->number);
            printf("修改后的信息为:%s %s %s\n", Current->name, Current->beizhu, Current->number);
            printf("修改成功!\n");
      }
    }
}

major_lyu 发表于 2020-2-25 17:08:28

黄翼 发表于 2020-2-23 23:36
您帮我测试一下,第二次调用查找函数就出错什么原因呢?

第二次调用查找函数出错是因为你第一次掉的时候查找函数最后的releaseInfo(New)把链表中的一部分结点删掉了,导致数据结构被破坏。New的前一个结点的next不等于Null,但是其指向的结点New已经吧free掉了。
具体看我在6楼的回复

黄翼 发表于 2020-3-2 19:12:48

major_lyu 发表于 2020-2-25 17:08
第二次调用查找函数出错是因为你第一次掉的时候查找函数最后的releaseInfo(New)把链表中的一部分结点删掉 ...

谢谢哈
页: [1]
查看完整版本: 在第二次调用查找函数的时候就出错,能帮我看看吗?