鱼C论坛

 找回密码
 立即注册
查看: 1250|回复: 9

[已解决]请大佬们指点一下

[复制链接]
发表于 2020-10-12 21:11:29 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
我的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-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为空崩溃  大部分情况来说并不是编译成功就能够实现目的 甚至有的时候你觉得运行没错了 换个数据样例输入就报错崩溃了.....
//慢慢来 我刚开始学也很头疼 多写写就会了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-10-12 21:54:20 | 显示全部楼层
可以把exit(0)换成return 0
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-10-12 22:48:32 | 显示全部楼层
金大师神父 发表于 2020-10-12 21:54
可以把exit(0)换成return 0

还是不行
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-10-12 23:38:40 | 显示全部楼层
本帖最后由 遗憾只藏心底 于 2020-10-12 23:47 编辑

例如
运行首先添加选择操作1 然后病人数 2
输入两个元素 xxx 1 boy 21 15555555555
                                    yyy 2 girl  22 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改变指向改变了什么。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2020-10-13 00:06:49 | 显示全部楼层
遗憾只藏心底 发表于 2020-10-12 23:38
例如
运行首先添加选择操作1 然后病人数 2
输入两个元素 xxx 1 boy 21 15555555555

谢谢大佬,我运行了几次也这样认为,但我还是不知道怎么改
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-10-13 09:21:55 | 显示全部楼层
一只老甲鱼 发表于 2020-10-13 00:06
谢谢大佬,我运行了几次也这样认为,但我还是不知道怎么改

定位序列号的话 直接利用p1=head,然后利用p1=p1->next遍历查找不就可以吗 我没看明白你为啥要p2 p1来回换着用
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-10-13 16:33:05 | 显示全部楼层
用DEV_C++编译,错误一大堆,我飘过了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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为空崩溃  大部分情况来说并不是编译成功就能够实现目的 甚至有的时候你觉得运行没错了 换个数据样例输入就报错崩溃了.....
//慢慢来 我刚开始学也很头疼 多写写就会了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-10-27 20:45:28 | 显示全部楼层
遗憾只藏心底 发表于 2020-10-13 21:30
#include
#include
using namespace std;

谢谢大佬指点
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

有道理,我nt了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-12 20:41

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表