如果前一个输入与当前输入相同,为什么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(),并给予被输入后新元素是元素相同链表中的任何元素sample output when input same as a element in linked list! [sample output when input is different from any previous linked list element如果前一个输入与当前输入相同,为什么cin的行为不同?

+0

如果您将列表操作的输入和输出分开,事情会变得更加容易。 (这看起来像是一个使用免费函数编写的程序,后来转化为“你必须使用类来传递课程”样式的C++程序。) – molbdnilo

一个大问题是您正在调用start的功能,即NULL,导致未定义的行为。在调用任何对象之前,实例化start

E.g.这很糟糕:

node *start=NULL,*end=NULL; 
// ... 
case 4: start->insert_after(&start,&end); 

您可能需要重新考虑您的设计。

所以,我会建议你,而不是实现你的行为与std::vector

+0

@Barry:看起来你的评论发生在我最后一次编辑的同时,所以我不确定你指的是什么。可能是开始和结束彼此指向的情况,在这种情况下,我会争辩说''n'根本不是真的被添加了两次,而是一次创建一个循环链表,这将破坏OP的'find'函数,所以我删除了我的答案的一部分。 – AndyG

+0

“start不指向结尾或反之亦然” Barry

+0

@巴里:道歉,我不清楚。正确或不正确的行为,我试图问OP的问题是他们是否希望能够通过'end-> prev'开始或通过'start-> next'结束。我同意一个元素的链表应该有'start == end',所以我将删除这个问题给OP。 – AndyG

的问题是在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->nextNULL,因此对​​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,所有的调用都是不确定的行为 - 但你不需要他们的方法呢,因为你”只能通过startend指针访问数据。

最后,这是为什么呢?

cin.clear(); 
cin.ignore(10000,'\n'); 

我很肯定你不需要这个程序。

+0

+1因为比我更关注'next'和'prev'这个问题,所以不会让你去你想要去的地方 – AndyG

+0

Hey Barry感谢你指出了insert_after方法中的错误。我没有得到的是你使用免费函数而不是类方法的建议。你可以点亮一下吗? – Parag