如果前一个输入与当前输入相同,为什么cin的行为不同?
问题描述:
#include<iostream>
using namespace std;
class node{
int data;
node *prev;
node *next;
public:
node(int n){
data=n;
prev=NULL;
next=NULL;
}
void insert_end(node**,node**);
void insert_beg(node**,node**);
void insert_after(node**,node**);
void delete_end(node**,node**);
void delete_start(node**,node**);
void display(node**,node**);
node* find(node**,node**,int n);
};
void node::insert_end(node **start,node **end){
int n;
if(*start!=NULL){
cout<<"Enter number \n";
cin>>n;
node *obj=new node(n);
(*end)->next=obj;
obj->prev=*end;
*end=(*end)->next;
}
else{
cout<<"Enter number \n";
cin>>n;
node *obj=new node(n);
*start=obj;
*end=obj;
}
}
void node::insert_beg(node **start,node **end){
int n;
if(*start!=NULL){
cout<<"Enter number \n";
cin>>n;
node *obj=new node(n);
(*start)->prev=obj;
obj->next=*start;
*start=obj;
}
else{
cout<<"Enter number \n";
cin>>n;
node *obj=new node(n);
*start=obj;
*end=obj;
}
}
void node::insert_after(node **start,node **end){
int n,nn;
if(*start!=NULL){
cout<<"Enter number \n";
cin>>n;
cout<<"Enter number after which element is to be inserted\n";
cin>>nn;
node *pos=find(start,end,nn);
if(pos==NULL){
cout<<"No such element "<<nn<<endl;
}
else{
node *obj=new node(n);
obj->prev=pos;
obj->next=pos->next;
pos->next->prev=obj;
pos->next=obj;
}
}
else{
cout<<"Enter number \n";
cin>>n;
cin.clear();
cin.ignore(10000,'\n');
node *obj=new node(n);
*start=obj;
*end=obj;
}
}
void node::display(node** start,node** end){
if(*start==NULL)cout<<"Empty list\n";
else{
node *temp=*start;
cout<<"List is :"<<endl;
while(temp!=NULL){
cout<<"\n"<<(temp)->data;
temp=(temp)->next;
}
}
}
void node::delete_end(node** start,node** end){
if(*start==NULL)cout<<"Empty list";
else{
node *temp=*end;
temp->prev->next=temp->next;
*end=(*end)->prev;
}
}
void node::delete_start(node** start,node** end){
if(*start==NULL)cout<<"Empty list";
else{
node *temp=*start;
temp->next->prev=NULL;
*start=(*start)->next;
}
}
node* node::find(node** start,node** end,int n){
node *temp=*start;
if(temp==NULL)return NULL;
else{
while(temp!=NULL){
if(temp->data==n)return temp;
else temp=temp->next;
}
return NULL;
}
}
int main(){
node *start=NULL,*end=NULL;
int choice,flag=0;
while(1){
cout<<"\n1.Exit\n2.Insert at end\n3.Insert at front\n4.Insert after\n5.Insert before\n6.Display\n7.Delete last\n8.Delete first\nMake Choice : ";
cin>>choice;
switch(choice){
case 1: flag=1;
break;
case 2: start->insert_end(&start,&end);
break;
case 3: start->insert_beg(&start,&end);
break;
case 4: start->insert_after(&start,&end);
break;
case 6: start->display(&start,&end);
break;
case 7: start->delete_end(&start,&end);
break;
case 8: start->delete_start(&start,&end);
break;
default:cout<<"Wrong input\n";
}
if(flag==1)break;
}
}
我得到一个分段错误(核心转储)当我打电话insert_after(),并给予被输入后新元素是元素相同链表中的任何元素如果前一个输入与当前输入相同,为什么cin的行为不同?
答
一个大问题是您正在调用start
的功能,即NULL
,导致未定义的行为。在调用任何对象之前,实例化start
。
E.g.这很糟糕:
node *start=NULL,*end=NULL;
// ...
case 4: start->insert_after(&start,&end);
您可能需要重新考虑您的设计。
所以,我会建议你,而不是实现你的行为与std::vector
。
答
的问题是在insert_after
成功案例:
node *obj = new node(n);
obj->prev = pos;
obj->next = pos->next;
pos->next->prev = obj; // <==
pos->next = obj;
如果我们有一个node
的列表,这是我们所期待的,所以pos
分给它的node
。在这种情况下,pos->next
为NULL
,因此对3210的分配将涉及取消引用NULL
,这可能是您的段错误的原因。
这部分应该是:
if (pos->next) {
pos->next->prev = obj;
}
else {
// no next? must be at the end
*end = obj;
}
这就是说,所有的node
方法应该是免费的功能,而不是类方法。您对insert_after
呼叫真的应该是这样的:
case 4:
insert_after(&start,&end);
break;
原样,因为你已经从start
作为NULL
,所有的调用都是不确定的行为 - 但你不需要他们的方法呢,因为你”只能通过start
或end
指针访问数据。
最后,这是为什么呢?
cin.clear();
cin.ignore(10000,'\n');
我很肯定你不需要这个程序。
如果您将列表操作的输入和输出分开,事情会变得更加容易。 (这看起来像是一个使用免费函数编写的程序,后来转化为“你必须使用类来传递课程”样式的C++程序。) – molbdnilo