pro1.1 cin,cout,cerr概念
cin 是 C++ 标准输入流对象,即 istream 类的对象。cin 主要用于从标准输入读取数据,这里的标准输入指终端键盘。
cout 是标准输出流对象,即 ostream 类的对象。
cerr 是标准错误输出流对象,也是 ostream 类的对象。
这里的标准输入指终端键盘,标准错误输出指终端屏幕。
pro1.2 输入输出与缓冲区
在理解 cin 功能时,不得不提标准输入缓冲区。当我们从键盘输入字符串的时候需要敲一下回车键才能够将这个字符串送入到缓冲区中,那么敲入的这个回车键(\r)会被转换为一个换行符(\n),这个换行符也会被存储在 cin 的缓冲区中并且被当成一个字符来计算!比如我们在键盘上敲下了 123456 这个字符串,然后敲一下回车键(\r)将这个字符串送入了缓冲区中,那么此时缓冲区中的字节个数是 7 ,而不是 6。
1.正常情况下:
cin 读取数据也是从缓冲区中获取数据,缓冲区为空时,cin 的成员函数会阻塞等待数据的到来,一旦缓冲区中有数据,就触发 cin 的成员函数去读取数据。
2.在错误情况下:
缓冲区
第一次我们输入了一个字母时,cin>>发现类型不匹配,会发生四种情况:
1.(cin>>a时)a的值保持不变/不会为变量赋值
2.不匹配的输入会被留在输入队列,也就是在缓冲区中不被读取
3.cin对象中的一个错误标记被设置为1,也就是上面提到的cin.fail(),在错误标记为1时后续无法读取缓存区数据。
4.对cin方法的调用将返回false(如果需要被转换为bool类型),(例如while(cin)后的语句将不会执行)
3.恢复错误(error recovering)
-step1:使用get、getline等方法去除缓存区中数据
解决情况2
-step2:使用cin.clear将错误标记恢复为0解决情况3
–上述问题情况已经全部解决
#include <iostream>
#include <string>
using namespace std;
int main()
{
char c;
int val=0;
int cnt;
//add a while loop for testing
while(cin){
cout<<'b'<<endl;
cin>>val;
cout<<"val = "<<val<<endl;
cout<<'a'<<endl;
cin.clear();//recover the fail mark from 1(false) to 0(true)
while ((c = getchar()) != '\n' && c != EOF&&c!=';');//remove the unwanted data from buffer
}
return 0;
}
pro2. 表达式被吃掉怎么办?
在使用输入输出流分词Token时,有时会遇见“前面表达式正常输出,最后一个表达式迟迟不来”的情况。
这不是程序的问题,而是出现了单词预读的问题。
什么是单词预读?
单词预读:一个表达式的结果不是被立刻输出,而被推迟到程序读入下一个表达式的第一个单词以后才能输出。
解决办法:加入一个输出命令(作为下一个表达式的单词)。可以用分号标识一个表达式的结束并触发结果的输出。
补充:有时可以再添加一个字符表示“退出命令”,搭配keep_window_open()使用体验更加哦!
pro3:一次输入,多个读取?
输入输出流的特性之一:(鄙视空集empty ignorance)
读取的字符会被空白符(空格、换行、tab字符)所终止。同时,空格在其他输入缺省的情况下会被">>“忽略,”>>"将会跳过空格读取后面的字符。
利用这个特性,可以通过在输入之间穿插空白符,结合多个">>",达到一次输入,读取多个结果的效果。
include<iostream>
include<string>
using namespace std;
int main(){
string first_name="???";
string last_name="???";
cin>>first_name>>last_name;
cout<<first_name<<last_name<<endl;
return 0;
}
鸣谢博主:
https://blog.csdn.net/qq_36437446/article/details/104092066
https://blog.csdn.net/k346k346/article/details/48213811
https://blog.csdn.net/weixin_43265881/article/details/88700819
参考书籍:
《C++程序设计-原理与实践》