手动生成链表中while(cin>>input)踩的坑

链表的结构是:

struct Listnode {
int val;
Listnode* next;
}

手动加入构造函数,现在是这样

struct ListNode{
    int val;
    ListNode* next;
    ListNode():val(0),next(nullptr){};
    ListNode(int x):val(x),next(nullptr){};
};

打算手动向ListNode* head1, ListNode* head2输入,代码如下

int main(){
    //输入链表1,以一个字母结尾
    ListNode* dummyHead1 = new ListNode(-1);
    ListNode* Node = dummyHead1;
    int input;
    while(cin>>input){
        Node->next = new ListNode(input);
        Node = Node -> next;
    }
    ListNode* listnode1 = dummyHead1->next;
    delete(dummyHead1);
    //输入链表2,以一个字母结尾
    ListNode* dummyHead2 = new ListNode(-1);
    Node = dummyHead2;
    while(cin>>input){
        Node->next = new ListNode(input);
        Node = Node -> next;
    }
    ListNode* listnode2 = dummyHead2->next;
    delete (dummyHead2);
}

在实际操作过程中,当我们输入1 2 3 a时,标准输入一直测试输入流的状态,并期待得到数字,当读取到a时,标准输入流产生了错误状态,因此while会停止,所以我们生成了1->2->3的链表。

1 2 3 a
1->2->3->   //忽略偷懒的最后一个箭头
Program ended with exit code: 0

但是我们的代码中明明有2个while,为什么刚输入完第一个就直接exit了呢?
通过断点,我们可以看到在语句while(cin>>input){处,while判定直接返回了false,是因为标准输入流此时仍然停留在错误状态上,因此我们需要清除标准输入流的错误状态

    cin.clear(); 
    //cin.clear()把cin的错误状态恢复正确,告诉标准库继续读区。

cin有如下几个状态,我们分别检查下当前状态是什么

    cout<<"goodbit? "<<cin.good()<<endl;
    cout<<"eofbit:已到达文件尾?" << cin.eof() << endl;
    cout<<"failbit:非致命的输入/输出错误,可挽回? " << cin.fail() <<endl;
    cout<<"badbit:致命的输入/输出错误,无法挽回?"<< cin.bad()<< endl;
    cout<<"after clear : "<<endl;

    cin.clear();
    
    cout<<"goodbit? "<<cin.good()<<endl;
    cout<<"eofbit:已到达文件尾?" << cin.eof() << endl;
    cout<<"failbit:非致命的输入/输出错误,可挽回? " << cin.fail() <<endl;
    cout<<"badbit:致命的输入/输出错误,无法挽回?"<< cin.bad()<< endl;

输出结果如下:

1 2 3 a
goodbit? 0
eofbit:已到达文件尾?0
failbit:非致命的输入/输出错误,可挽回? 1
badbit:致命的输入/输出错误,无法挽回?0
after clear : 
goodbit? 1
eofbit:已到达文件尾?0
failbit:非致命的输入/输出错误,可挽回? 0
badbit:致命的输入/输出错误,无法挽回?0

因此我们可以看到,通过cin.clear(),此时错误状态被清空。我们知道cin只有在缓冲区为空的时候才会提示我们去输入,如果里面有值的话,是不会提示我们输入,直接取出字符的。此时a仍然滞留在缓冲区中,无法被读出,下一次做while判断的时候仍然会返回false。
因此我们将利用如下函数ignore,其默认参数为(1,EOF),即当其碰到EOF时或者ignore了一个字符时停止,看哪个先到。

    cin.ignore(a,ch); 
    //如果计数值达到a或者被抛弃的字符是ch,则cin.ignore()函数执行终止;否则,它继续等待。
    //它的一个常用功能就是用来清除以回车结束的输入缓冲区的内容,消除上一次输入对下一次输入的影响。

现在我们试试如下代码

    cin.ignore();//清空
    cin.clear();//重置 

还是只能执行一个while,第二个cin>>input返回false。但是当执行以下代码的时候,却可以正常执行第二个while,输出第二段链表了。why?

    cin.clear();//重置 
    cin.ignore();//清空

当我们先用ignore的时候,即先执行清空操作,此时由于状态位中fail仍然保持,因此清空操作无效,哪怕之后clear了状态位,下一轮while循环仍然会读入当前流中未输出的输入,在此情况下即为无效的a。只有先clear重置了所有状态位,才能进行ignore清空操作,此时才能成功清空。

此时终于成功生成了两个链表了。

9 9 9 a
9 b
1->0->0->8

并且还成功过做了加法,我可太牛逼了,叉会腰。

优化以下代码,要求:班级成绩管理系统 (1)利用结构体和简单的链表,实现一个班学生成绩的管理,至少可以输入20个学生的成绩。 (2)成绩管理功能包括:输入、输出,利用new和delete运算符添加和删除班级成绩 (1)利用结构体和简单的链表(关于链表的知识,自己查阅资料学习),实现一个班学生成绩的管理。#include<stdio.h> #include<iostream> #include<windows.h> using namespace std; typedef struct student { char name[20]; int score; student* next; }stu; stu* head; void input() { stu* p1, * p2; p1 = (stu*)new stu; head = p1; while (p1 != NULL) { cout << "输入姓名" << endl; cin >> p1->name; cout << "输入成绩" << endl; cin >> p1->score; cout << "是否继续输入?(1.是 2.否)"; int a; cin >> a; if (a == 1) { p2 = p1; p1 = (stu*)new stu; p2->next = p1; continue; } else if (a == 2) { p1->next = NULL; break; } } } void listprint() { stu* p1 = head; while (p1 != NULL) { cout << 1; cout << "姓名: " << p1->name << " 成绩:" << p1->score << endl; p1 = p1->next; } } void shanchu() { char c[20]; cout << "请输入删除的学生姓名" << endl; cin >> c; stu* p1 = head, * p2; while (p1 != NULL) { p2 = p1->next; if (strcmp(p2->name, c) == 0) { p1->next = p2->next; break; }p1 = p1->next; } } int main() { int a = 0; while (1) { cout << "1.输入成绩 2.输出成绩 3.删除" << endl;cin >> a; switch (a) { case 1: { input(); system ("cls"); continue; } case 2: { listprint(); continue; } case 3: { shanchu(); continue; } default: { break; } } break; } }
03-11
优化以下代码,要求:班级成绩管理系统 (1)利用结构体和简单的链表(关于链表的知识,自己查阅资料学习),实现一个班学生成绩的管理。 (2)成绩管理功能包括:输入、输出,利用new和delete运算符添加/删除班级成绩管理系统 (1)利用结构体和简单的链表(关于链表的知识,自己查阅资料学习),实现一个班学生成绩的管理。 (2)成绩管理功能包括:输入、输出,利用new和delete运算符添加/删除学生信息。#include<stdio.h> #include<iostream> #include<windows.h> using namespace std; typedef struct student { char name[20]; int score; student* next; }stu; stu* head; void input() { stu* p1, * p2; p1 = (stu*)new stu; head = p1; while (p1 != NULL) { cout << "输入姓名" << endl; cin >> p1->name; cout << "输入成绩" << endl; cin >> p1->score; cout << "是否继续输入?(1.是 2.否)"; int a; cin >> a; if (a == 1) { p2 = p1; p1 = (stu*)new stu; p2->next = p1; continue; } else if (a == 2) { p1->next = NULL; break; } } } void listprint() { stu* p1 = head; while (p1 != NULL) { cout << 1; cout << "姓名: " << p1->name << " 成绩:" << p1->score << endl; p1 = p1->next; } } void shanchu() { char c[20]; cout << "请输入删除的学生姓名" << endl; cin >> c; stu* p1 = head, * p2; while (p1 != NULL) { p2 = p1->next; if (strcmp(p2->name, c) == 0) { p1->next = p2->next; break; }p1 = p1->next; } } int main() { int a = 0; while (1) { cout << "1.输入成绩 2.输出成绩 3.删除" << endl;cin >> a; switch (a) { case 1: { input(); system ("cls"); continue; } case 2: { listprint(); continue; } case 3: { shanchu(); continue; } default: { break; } } break; } }
03-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值