一只老甲鱼 发表于 2020-10-12 21:11:29

请大佬们指点一下

我的while语句里switch并没有选择case 0;但选择1~5几次后就自动结束程序了,搞不懂问题出在哪,代码如下
#include<iostream>
#include<string>
using namespace std;

typedef struct patient{
    int num;//序号
    string sex;
    string name;
        int age;
        string phonenumber;   
    struct patient *next;
}pat;

pat *head=NULL;

void test(); // 测试头指针是否为空
void creat();//记录信息
void insert();//添加信息
void del();//删除信息
void locate();//定位信息
void print();//显示信息


int main()
{
    int choice;
    cout<<"\t\t\t\t\t\t病人信息管理系统\n\n";
    cout<<"0.退出系统\t1.记录信息\t2.定位信息\t3.删除信息\t4.添加信息\t5.显示信息\n";
    cout<<"输入选择(0-5): ";
    cin>>choice;
    while(1)
    {
      switch(choice)
      {
            case 0: exit(0);
            case 1: creat();   break;
            case 2: locate();   break;
            case 3: del();   break;
            case 4: insert();   break;
            case 5: print();   break;
         default: cout<<"输入有误!\n";   break;
      }
      cout<<"输入选择(0-5): ";
      cin>>choice;
    }
    return 0;
}

void test()
{
        if (!head)
        {
            cout << "head NULL\n";
            exit(-1);
    }
}

void creat()
{
    pat *p1,*p2;
    int i,n;
    cout<<"输入病人人数: ";
    cin>>n;
    i=0;       
    while(i<n)
    {
      p1=new pat;
      if(NULL==head)
      {
            head=p1;
            p2=head;
      }
      else
      {
                        cout<<"输入病人信息:姓名\t序号\t性别\t年龄\t电话号码\n";
            cin>>p1->name>>p1->num>>p1->sex>>p1->age>>p1->phonenumber;
            p2->next=p1;
            p2=p1;
            i++;
      }
    }
}

void locate()
{
        pat *p1,*p2;
        int num;
        cout<<"输入要定位病人的序号:";
        cin>>num;
        test();
        p2=head;
        p1=p2->next;
        while(1)
        {
                if(p1->num==num)
                {
                        p2->next=p1->next;
                        cout<<"输出定位病人信息:姓名序号    性别    年龄    电话号码\n";
                        cout<<"\t\t"<<' '<<p1->name<<"\t"<<p1->num<<"\t"<<p1->sex<<"\t"<<p1->age<<"\t"<<p1->phonenumber<<"\t"<<endl;
                        break;
                }
                p2=p1;
                p1=p2->next;
        }
}

void insert()
{
    pat *p1;
    p1=new pat;
    cout<<"输入新增病人的名字序号性别年龄电话号码: ";
    cin>>p1->name>>p1->num>>p1->sex>>p1->age>>p1->phonenumber;
    p1->next=head->next;
    head->next=p1;
}


void del()
{
    pat *p1,*p2;
    int num;
    cout<<"输入要删除病人的序号: ";
    cin>>num;
    test();
    p2=head;
    p1=p2->next;
    while(1)
    {
      if(p1->num==num)
      {
            p2->next=p1->next;
            delete p1;
            break;
      }
      p2=p1;
      p1=p2->next;
    }
}

void print()
{
    pat *p1;
    test();
    p1=head->next;
    while(p1)
    {
      cout<<p1->name<<p1->sex<<p1->age<<p1->phonenumber<<endl;
      p1=p1->next;
    }
}

金大师神父 发表于 2020-10-12 21:54:20

可以把exit(0)换成return 0

一只老甲鱼 发表于 2020-10-12 22:48:32

金大师神父 发表于 2020-10-12 21:54
可以把exit(0)换成return 0

还是不行

遗憾只藏心底 发表于 2020-10-12 23:38:40

本帖最后由 遗憾只藏心底 于 2020-10-12 23:47 编辑

例如
运行首先添加选择操作1 然后病人数 2
输入两个元素 xxx 1 boy 21 15555555555
                                    yyy 2 girl22 16666666666
然后选择2 定位信息 查找序号为1的
再次选择2 定位信息 查找序号为1的 程序崩溃

locate函数里面的
        p2=head;
      p1=p2->next;
      while(1).
      {
                if(p1->num==num)
                {
                        p2->next=p1->next;
这一段,当运行的 p2->next=p1->next; 此时是head->next=head->next->next,意思就是头节点的下一个节点是头节点的下一个节点的下一个节点,则头节点->next指向的第一个元素被吞掉了。

只运行了一小段,而且程序运行直接选择添加信息的时候,同样崩溃,因为此时head为空无法直接添加。
电脑没电了,来不及运行了。个人感觉就是next导致节点被吞,指针为空没new导致的。需要具体确切去确认一下每次next改变指向改变了什么。

一只老甲鱼 发表于 2020-10-13 00:06:49

遗憾只藏心底 发表于 2020-10-12 23:38
例如
运行首先添加选择操作1 然后病人数 2
输入两个元素 xxx 1 boy 21 15555555555


谢谢大佬,我运行了几次也这样认为,但我还是不知道怎么改

遗憾只藏心底 发表于 2020-10-13 09:21:55

一只老甲鱼 发表于 2020-10-13 00:06
谢谢大佬,我运行了几次也这样认为,但我还是不知道怎么改

定位序列号的话 直接利用p1=head,然后利用p1=p1->next遍历查找不就可以吗 我没看明白你为啥要p2 p1来回换着用

乐乐学编程 发表于 2020-10-13 16:33:05

用DEV_C++编译,错误一大堆,我飘过了

遗憾只藏心底 发表于 2020-10-13 21:30:29

本帖最后由 遗憾只藏心底 于 2020-10-13 21:52 编辑

#include<iostream>
#include<string>
using namespace std;

typedef struct patient{
    int num;//序号
    string sex;
    string name;
      int age;
      string phonenumber;
    struct patient *next;
}pat;

pat *head=NULL;

void test(); // 测试头指针是否为空
void creat();//记录信息
void insert();//添加信息
void del();//删除信息
void locate();//定位信息
void print();//显示信息


int main()
{
    int choice;
    cout<<"\t\t\t\t\t\t病人信息管理系统\n\n";
    cout<<"0.退出系统\t1.记录信息\t2.定位信息\t3.删除信息\t4.添加信息\t5.显示信息\n";
    cout<<"输入选择(0-5): ";
    cin>>choice;
    while(1)
    {
      switch(choice)
      {
            case 0: exit(0);
            case 1: creat();   break;
            case 2: locate();   break;
            case 3: del();   break;
            case 4: insert();   break;
            case 5: print();   break;
         default: cout<<"输入有误!\n";   break;
      }
      cout<<"输入选择(0-5): ";
      cin>>choice;
    }
    return 0;
}

void test()
{
      if (head==NULL||(head->next)==NULL)//head->next也不为空是为了保险起见
      {
            cout << "没有病人\n";
            exit(-1);
    }
}

void creat()
{
    pat *p1,*p2;
    int n,first=1;
    cout<<"输入病人人数: ";
    cin>>n;
    //首次输入的时候需要将病人记录与head相连接,first变量是为了检测是否是第一次输入
    if(first)
    {
      head=new pat;//没有此行会报错
      p2=new pat;
      head->next=p2;
      cout<<"输入病人信息:姓名\t序号\t性别\t年龄\t电话号码\n";
      cin>>p2->name>>p2->num>>p2->sex>>p2->age>>p2->phonenumber;
      first=0;
      n--;
    }
    while(n--)//利用n-- 删去楼主的i 因为利用n--就可以实现计数输入病人记录 代码更加简洁
    {
      p1=new pat;
      cout<<"输入病人信息:姓名\t序号\t性别\t年龄\t电话号码\n";
      cin>>p1->name>>p1->num>>p1->sex>>p1->age>>p1->phonenumber;
      p2->next=p1;
      p2=p2->next;//这里p2始终保持最后一个记录 所以每次写入新纪录之后 只需要p2->next=p1 就可以完成连接
    }
}

void locate()
{
      pat *p1;
      int num;
      cout<<"输入要定位病人的序号:";
      cin>>num;
      test();
      p1=head->next;//首位病人 最好是先检测head->next是否为NULL 写注释时候我才想到应该先检测 不然未插入直接选择定位功能的话往下运行会出错
      while(1)
      {
                if(p1->num==num)
                {
                        cout<<"输出定位病人信息:姓名序号    性别    年龄    电话号码\n";
                        cout<<"\t\t"<<' '<<p1->name<<"\t"<<p1->num<<"\t"<<p1->sex<<"\t"<<p1->age<<"\t"<<p1->phonenumber<<"\t"<<endl;
                        break;
                }
                else if((p1->next)==NULL)//当p1->next==NULL的时候还未找到该序号的病人 则证明查无此人
                {
                  cout<<"查无此人\n";
                  break;
                }
                else
                {
                  p1=p1->next;//保持往下遍历
                }
      }
}

void insert()//原文的插入是直接插在了head后面 这种做法很不可取 如果原来有三个病人 直接插在head后面会导致连接断开
{
    pat *p1,*p2;
    p1=new pat;
    cout<<"输入新增病人的名字序号性别年龄电话号码: "<<endl;
    cin>>p1->name>>p1->num>>p1->sex>>p1->age>>p1->phonenumber;
    p2=head;//找到最后一个病人的位置 在最后一个病人位置后插入新病人信息
    while((p2->next)!=NULL)
    {
      p2=p2->next;
    }
    p2->next=p1;
    cout<<"添加完毕\n";
}


void del()
{
    pat *p1,*p2;
    int num;
    cout<<"输入要删除病人的序号: ";
    cin>>num;
    test();
    p1=head;
      while(1)
      {
                if((p1->next)==NULL)//如果while循环像locate一样先检测num是否相等即将此if和下面else if 语句互换顺序 会报错,因为else if里面使用到了p1->next 如果为空则访问不到p1->next->num 会退出运行
                {
                  cout<<"查无此人\n";
                  break;
                }
                else if(p1->next->num==num)//此时p1->next指向的才是要删除的病人
                                    //此时有两种情况 一种是删除的病人后面还有病人 只需要让目前p1的next指向下下个病人即可
                                    //另外一种情况是 要删除的病人就是最后一个人 则让p1的next指向空即可
                {
                  if((p1->next->next)!=NULL)
                  {
                        (p1->next)=(p1->next->next);
                  }
                  else
                  {
                        p1->next=NULL;
                  }
                  cout<<"删除完毕"<<endl;
                  break;
                }
                else
                {
                  p1=p1->next;
                }
      }
}

void print()
{
    pat *p1;
    test();
    p1=head->next;
    while(p1)
    {
      cout<<"\t\t"<<' '<<p1->name<<"\t"<<p1->num<<"\t"<<p1->sex<<"\t"<<p1->age<<"\t"<<p1->phonenumber<<"\t"<<endl;
      p1=p1->next;
    }
}

具体运行情况
                                             病人信息管理系统

0.退出系统      1.记录信息      2.定位信息      3.删除信息      4.添加信息      5.显示信息
输入选择(0-5): 1
输入病人人数: 3
输入病人信息:姓名       序号    性别    年龄    电话号码
xpc 1 boy 21 110
输入病人信息:姓名       序号    性别    年龄    电话号码
wws 2 boy 22 120
输入病人信息:姓名       序号    性别    年龄    电话号码
zzy 3 boy 19 119
输入选择(0-5): 2
输入要定位病人的序号:1
输出定位病人信息:姓名序号    性别    年龄    电话号码
                xpc    1       boy   21      110
输入选择(0-5): 2
输入要定位病人的序号:2
输出定位病人信息:姓名序号    性别    年龄    电话号码
               wws    2       boy   22      120
输入选择(0-5): 2
输入要定位病人的序号:3
输出定位病人信息:姓名序号    性别    年龄    电话号码
                zzy    3       boy   19      119
输入选择(0-5): 2
输入要定位病人的序号:4
查无此人
输入选择(0-5): 2
输入要定位病人的序号:5
查无此人
输入选择(0-5): 4
输入新增病人的名字序号性别年龄电话号码:
zml 4 boy 20 911
添加完毕
输入选择(0-5): 5
                xpc    1       boy   21      110
               wws    2       boy   22      120
               zzy    3       boy   19      119
               zml    4       boy   20      911
输入选择(0-5): 3
输入要删除病人的序号: 2
删除完毕
输入选择(0-5): 5
               xpc    1       boy   21      110
               zzy    3       boy   19      119
               zml    4       boy   20      911
输入选择(0-5): 0

Process returned 0 (0x0)   execution time : 80.009 s
Press any key to continue.

//这种的主要是细心 考虑情况的全一点 可以拓展一下按序号排序记录 插入操作到某位置的而不只是插入到最后这类的操作怎么写
//一步一步去看 连接到了那里 会不会next为空崩溃大部分情况来说并不是编译成功就能够实现目的 甚至有的时候你觉得运行没错了 换个数据样例输入就报错崩溃了.....
//慢慢来 我刚开始学也很头疼 多写写就会了

一只老甲鱼 发表于 2020-10-27 20:45:28

遗憾只藏心底 发表于 2020-10-13 21:30
#include
#include
using namespace std;


谢谢大佬指点

一只老甲鱼 发表于 2020-10-27 20:46:37

遗憾只藏心底 发表于 2020-10-13 09:21
定位序列号的话 直接利用p1=head,然后利用p1=p1->next遍历查找不就可以吗 我没看明白你为啥要p2 p1来回换 ...

有道理,我nt了
页: [1]
查看完整版本: 请大佬们指点一下