visual。猥琐。纠结人的bug。求救。。。关于电话本,在删除一个成员的时候,delete有问题,加*的地方,但是放在dev就没有问题。
程序代码:
#include<iostream> #include<fstream> #include<iomanip> #include<cstdlib> using namespace std; typedef struct call{ char name[20]; char telenum[12]; struct call*nextPtr; }call;//链表包括 成员的名字和电话号码,还有指针 call*deletePtr;//用于存储要被删除成员的位置 call*solPtr=NULL;//表示要插入的位置 call*startPtr=NULL;//链表开始的位置 class telephone//每一个成员的对象 { public: telephone(){}//构造函数 void add(telephone &tel);//每一个对象都可以添加到电话本中 void set1(char ch[20],telephone &tel);//每一个对象都需要有姓名 void set2(char ch1[12],telephone &tel);//每一个对象都需要有号码 void delete_num(call*p1);//每一个对象都可以被删除 call* research(telephone &tel);//每一个对象都可以被查找 void change(call*p);//每一个对象都可以被重新编辑 ~telephone(){} private: char Pname[20]; char Ptelenum[12];//电话本的每一个对象都必须有名字和号码 }; void telephone::add(telephone& tel)//把一个对象添加到电话本中,通过引用传值,为了调用对象的私有成员 { call* currentPtr=NULL;//当前处理的一个指针 call* newPtr=new call;//有new动态申请一个指向 call*pptr;//用于打印时候的的指针,防止全局变量被改变 int i; for(i=0;i<20;i++) newPtr->name[i]='\0'; for(i=0;i<20;i++) newPtr->telenum[i]='\0'; for(i=0;i<20;i++) newPtr->name[i]=tel.Pname[i]; for(i=0;i<12;i++) newPtr->telenum[i]=tel.Ptelenum[i];//把类里面的私有成员赋值给链表中的 if(startPtr!=NULL)//如果添加的对象不是第一个 { if(solPtr==startPtr)//如果要插入的位置是在链表开始的位置的前后 { for(i=0;i<20;i++) if((startPtr->name[i]-'a')!=(newPtr->name[i]-'a')) break;//再次比较在第几个字符的地方,新添的对象与开始的位置不同 if((startPtr->name[i]-'a')>(newPtr->name[i]-'a'))// { currentPtr=startPtr; startPtr=newPtr; startPtr->nextPtr=currentPtr;//在链表的开始插入对象,重新定义链表头 } else//如果在开始位置后面插入就与平时的链表的插入相似 { currentPtr=solPtr->nextPtr; solPtr->nextPtr=newPtr; newPtr->nextPtr=currentPtr; } } else { currentPtr=solPtr->nextPtr;//如果不是在链表开始位置的前后.链表的插入工作 solPtr->nextPtr=newPtr; newPtr->nextPtr=currentPtr; } } else { startPtr=newPtr; startPtr->nextPtr=NULL;//如果是第一次开始的链表的插入 } cout<<"增加成功"<<endl; pptr=startPtr;//从头开始打印 while(pptr!=NULL) {cout<<pptr->name<<"->"; pptr=pptr->nextPtr; } } void telephone::delete_num(call*p1)//删除链表 { call* currentPtr=NULL; call*pptr=NULL; call*p2=new call; if(p1==startPtr) startPtr=startPtr->nextPtr; else//删除一般位置的节点 {currentPtr=p1->nextPtr; deletePtr->nextPtr=currentPtr;} //p1=currentPtr; delete p1;//****************************************************************************************************** cout<<"删除成功"<<endl; pptr=startPtr;//从链表头开始打印 while(pptr!=NULL) {cout<<pptr->name<<"->"; pptr=pptr->nextPtr; } } call* telephone::research(telephone &tel)//查找姓名 { call*Ptrtel=startPtr; call*temPtr=startPtr; int i; int j=0; while(Ptrtel!=NULL) { for(i=0;i<20;i++) { if(tel.Pname[i]!=Ptrtel->name[i]) break; }//比较在第几个字符的地方,新添的对象与开始的位置不同 if(i==20) { if(Ptrtel!=startPtr) deletePtr=temPtr;//如果位置靠前,其删除位置就是其前面的指针 return Ptrtel;//如果有找到该字符串,就返回其插入的位置 } else if(i>=j) { if((tel.Pname[i]-'a')>=(Ptrtel->name[i]-'a'))//如果字符位置靠后, { solPtr=Ptrtel;//插入位置是就是这个地方 temPtr=Ptrtel;//得到它之前的位置的指针 } else solPtr=temPtr;//如果位置靠前,其插入位置就是其前面的指针 j=i;//为了比较与那个字符的名字相似度最大 } Ptrtel=Ptrtel->nextPtr;//循环查找 } return Ptrtel;//没有找到,返回空值 } void telephone::change(call*p)//改变成员的内容 { int m,n,i; call*p1=startPtr; cout<<"请修改新旧成员的名字吗?1----修改,2----不修改"<<endl; cin>>m; if(1==m)//如果想要改变成员的名字 { cout<<"请输入新的名字"<<endl; for(i=0;i<20;i++) p->name[i]='\0'; cin>>p->name;//输入名字 while(p1!=NULL) { for(i=0;i<20;i++) if(p1->name[i]!=p->name[i]) break;//如果名字中有一个不相同就跳出与其的比较 p1=p1->nextPtr;//与下一个比较 if(i==20)//如果i==20说明该成员已经存在 { getchar(); cout<<"该成员已经存在"<<endl; cout<<"请输入新的名字"<<endl; for(i=0;i<20;i++) p->name[i]='\0'; cin>>p->name; p1=startPtr;//输入新的名字,重新比较 } if(p1==p) p1=p1->nextPtr;//跳过与自己的比较 } cout<<"修改成功"<<endl; } cout<<"想修改新旧成员的号码?1----修改,2----不修改"<<endl; cin>>n;//是否修改号码 if(1==n) { cout<<"请输入新的号码"<<endl; cin>>p->telenum; cout<<"修改成功"<<endl; } } void telephone::set1(char ch[20],telephone &tel)//设置类里面的成员 { int i; for(i=0;i<20;i++) tel.Pname[i]=ch[i]; } void telephone::set2(char ch1[12],telephone &tel)//设置类里面的成员 { int i; for(i=0;i<12;i++) tel.Ptelenum[i]=ch1[i]; } int main() { int i=0,j; int ocasion;//用于选择要用的功能 char ch1;//在读文件时候,是否结束 char newname[20]; char newtelenum[12];//存储初始化新的对象的变量 char ch;//用于判断是否继续操作的变量 call*p;//用于输入到文件的指针 call*ptr;//接收查找指针返回的位置,用于插入新的对象 call*pptr=new call; ofstream file;//建立输出流文件,把链表的信息读到文件 ifstream tfile; //建立一个输入流文件,用于把文件中的信息读到链表中 tfile.open("contact.dat");//打开文件 if(tfile.fail()) cout<<"fail"<<endl;//如果问价打开失败 else//如果文件成功的打开 { ch1=tfile.get();//读取一个字符,判断是否空文件 tfile.seekg(-1,ios::cur);//把指针退回到文件开始的时候 if(((ch1-'A')>=0&&(ch1-'Z')<=0)||((ch1-'a')>=0&&(ch1-'z')<=0))//如果不是空文件 { cout<<"电话本中已存在如下的成员"<<endl; while(!tfile.eof()) //如果文件没有结束 { tfile.getline(pptr->name,19,'\t');//读取前面的字符到指针的姓名数组中 tfile.seekg(3,ios::cur);//读取一个空字符和两个\t字符 tfile.getline(pptr->telenum,12);//读取剩下的字符到指针的号码数组中 for(j=0;j<20;j++) if(((pptr->name[j]-'A')>=0&&(pptr->name[j]-'Z')<=0)||((pptr->name[j]-'a')>=0&&(pptr->name[j]-'z')<=0)) {} else pptr->name[j]='\0';//为了以后与新加入的成员姓名比较,就把不是字母的字符赋值为空 for(j=0;j<20;j++) if(((pptr->telenum[j]-'0')>=0&&(pptr->telenum[j]-'9')<=0)) {} else pptr->telenum[j]='\0';//电话号码也是如此 if(i<1) startPtr=pptr; cout<<pptr->name<<"\t\t"<<pptr->telenum<<endl; pptr->nextPtr=NULL;//把指向下一个结构的指针赋值为空, ++i;//仅仅是为了只给StartPtr赋值一次 ch1=tfile.get();//再次读取一个字符,判断是否文件结束 tfile.seekg(-1,ios::cur);//后退一个字符到每一行的开始 if(((ch1-'A')>=0&&(ch1-'Z')<=0)||((ch1-'a')>=0&&(ch1-'z')<=0)) {} else break;//如果下一行是空,跳出循环 call*tr=new call;//没有结束就申请一个新的结构 pptr->nextPtr=tr;//把新申请的结构加入链表 pptr=pptr->nextPtr;//把下一个结构的地质赋值给pptr } } tfile.close();//关闭文件 } file.open("contact.dat",ios_base::trunc);//定义一个文件,用trunc方式打开 telephone newone;//构建一个新的类 cout<<"开始操作吗?Y/N"<<endl; cin>>ch; while(ch=='Y') { cout<<"请输入你要使用的功能:"<<endl; cout<<"1--------添加成员"<<endl; cout<<"2--------删除成员"<<endl; cout<<"3--------查找成员"<<endl; cout<<"4--------编辑成员"<<endl; cin>>ocasion; for(i=0;i<20;i++) newname[i]='\0'; for(i=0;i<12;i++) newtelenum[i]='\0'; switch(ocasion) { case 1://添加新成员 cout<<"请输入新成员的名字"<<endl; cin>>newname; getchar();// cout<<"请输入新成员的电话号码"<<endl; cin>>newtelenum; newone.set1(newname,newone); newone.set2(newtelenum,newone);//给类里面的私有成员赋值 if(startPtr==NULL)//如果新添加的对象是第一个 newone.add(newone); //用链表在相应位置添加 else { //如果新添加的对象不是第一个,就查找名字是否存在 while((ptr=newone.research(newone))!=NULL) { cout<<"该姓名已经存在"<<endl; cout<<"请输入新成员的名字"<<endl;//查找不成功就提示不存在 for(i=0;i<20;i++) newname[i]='\0'; getchar(); cin>>newname; cout<<"请输入新成员的电话号码"<<endl; for(i=0;i<12;i++) newtelenum[i]='\0'; getchar(); cin>>newtelenum; newone.set1(newname,newone); newone.set2(newtelenum,newone);//给类里面的私有成员赋值 } newone.add(newone); //然后把符合要求的成员加进去 } break; case 2://删除一个成员 cout<<"请输入要删除成员的名字"<<endl; cin>>newname; newone.set1(newname,newone);//设置对象的私有成员 while((ptr=newone.research(newone))==NULL) { cout<<"该成员不存在,请输入正确的名字"<<endl;//如果在链表中没有找到,提示该成员不存在 cout<<"请输入要删除的名字"<<endl; getchar(); for(i=0;i<20;i++) newname[i]='\0'; cin>>newname; newone.set1(newname,newone);//给类里面的私有成员赋值 } newone.delete_num(ptr);//找到就删除 break; case 3://查找一个成员 cout<<"请输入目标成员的名字"<<endl; cin>>newname; newone.set1(newname,newone);//设置对象的私有成员 if((ptr=newone.research(newone))==NULL) { getchar(); while((ptr=newone.research(newone))==NULL) { cout<<"该成员不存在,请输入正确的名字"<<endl;//如果在链表中没有找到,提示该成员不存在 cout<<"请输入要查找的名字"<<endl; for(i=0;i<20;i++) newname[i]='\0'; cin>>newname; newone.set1(newname,newone);//给类里面的私有成员赋值 } cout<<"name"<<" "<<ptr->name<<endl; cout<<"phone_num"<<" "<<ptr->telenum<<endl; } else { cout<<"name"<<" "<<ptr->name<<endl; cout<<"phone_num"<<" "<<ptr->telenum<<endl; }//找到就打印成员信息 break; case 4://修改一个成员信息 cout<<"请输入目标成员的名字"<<endl; cin>>newname; newone.set1(newname,newone);//设置对象的私有成员 if((ptr=newone.research(newone))==NULL) { getchar(); while((ptr=newone.research(newone))==NULL) { cout<<"该成员不存在,请输入正确的名字"<<endl;//如果在链表中没有找到,提示该成员不存在 cout<<"请输入新成员的名字"<<endl; for(i=0;i<20;i++) newname[i]='\0'; cin>>newname; newone.set1(newname,newone);//给类里面的私有成员赋值 } newone.change(ptr);//找到就改变信息 cout<<"name"<<" "<<ptr->name<<endl; cout<<"phone_num"<<" "<<ptr->telenum<<endl; } else { newone.change(ptr);//找到就改变信息 cout<<"name"<<" "<<ptr->name<<endl; cout<<"phone_num"<<" "<<ptr->telenum<<endl; } break; default: cout<<"fail"<<endl; break; } getchar(); cout<<endl<<"继续操作吗? Y/N"<<endl; cin>>ch; if(ch=='N')//如果不再操作,就把链表打印到链表 { p=startPtr; while(p!=NULL) { file<<p->name<<"\t\t\t"<<setiosflags(ios_base::left)<<p->telenum<<endl; p=p->nextPtr; file<<resetiosflags(ios_base::left);//设置相应的打印格式 } } } // delete pptr; // delete tr; **************************************delete与free的区别 file.close(); system("pause"); return 0; }