cin/cout 的本质是流,cin 是输入流(istream),cout 是输出流(ostream)。
- 进制:
- 默认十进制输出:cout << dec << 100 << endl;
- cout << hex << (unsigned int)(0) - 1 << endl; // ffffffff
- cout << oct << 10 << endl; // 12
1. 楔子
int a;
try
{
if (!(cin>>a))
throw Invalid_number();
}
catch(Invalid_number)
{
cerr << "You must input an integer.\n";
return -1;
}
当在控制台输入一个 double 类型的小数时(比如 5.3),程序并未抛出并捕获异常(a = 5)。
int a, b;
std::cin >> a >> b;
std::cout << a + b << std::endl;
// 在控制台输入: 3 5.3
// 输出为:8
// 在控制台输入:3.3 5
// 输出为:-858993457(也即为垃圾值)
// 单步调试的话,会发现 a = 3, b 为垃圾值,也即并未将整数 5 正常赋值给 b
cin 并未做强制类型转换,它做的更像是一种截断,只保留小数点.
之前的部分,又因为流
的特性,会继续在缓冲区中取值,赋给待赋值的变量。
当需要读取一个整型,却在控制台给它一个 1.5 的输入时,程序会把它看做整数 1,程序会停止小数点的位置,因为它不是整形的一部分,但是因为流
的特性,.5
仍然存在于输入中(残留数据)1。
2. 输入原理2
程序的输入都建有一个缓冲区,即输入缓冲区。一次与控制台交互的输入的过程是这样的,当一次键盘输入结束时会将输入的数据存入输入缓冲区,而 cin
会直接从输入缓冲区中读取数据。正因为 cin
是直接从缓冲区取数据的,所以有时候当缓冲区有残留数据时,cin
会直接取得这些残留数据而不会再请求键盘输入。
char str[8];
cin.getline(str, 5);
// 在控制台输入:abcdefg
cout << str << endl;
// abcd
// str[0] = 'a'
// str[1] = 'b'
// str[2] = 'c'
// str[3] = 'd'
// str[4] = '\0'
cin.getline(str, 5);
cout << str << endl;
// 不经历第二次输入,而是直接输入换行,程序退出
// str[0] = '\0'
// str[1] = 'b'
// str[2] = 'c'
// str[3] = 'd'
// str[4] = '\0'
// ...
3. cin >>
输入结束的条件,遇到 enter,space,tab 键
对结束符的处理:丢弃缓冲区中所有使得输入结束的结束符(enter、space、tab)
char str1[10], str2[10];
cin >> str1 >> str2;
// 我们可以在输入完毕 str1 之后,按下多个回车或空格再进行第二个变量的赋值
4. cin.get():读取含空格的字符串
其中结束符为可选参数,读入的字符个数最多为(长度-1)个,若要读取字符,直接 cin.get(char ch)
或 ch = cin.get()
即可
对结束符的处理:不丢弃缓冲区中的 Enter(’\n’)
char c1, c2;
cin.get(c1); cin.get(c2);
cout << c1 << " " << c2 << endl;
// 打印这两个字符
cout << (int)c1 << " " << (int)c2 << endl;
// 打印这两个字符的 ASCII码值
测试一输入:
a[Enter]
输出:
a
97 10
【分析】会发现只执行了一次从键盘输入,显然第一个字符变量取的’a’, 第二个变量取的是Enter(ASCII值为10),这是因为该函数不丢弃上次输入结束时的Enter字符,所以第一次输入结束时缓冲区中残留的是上次输入结束时的Enter字符!
5. cin.getline()
cin.getline(数组名,长度,结束符) 大体与 cin.get(数组名,长度,结束符)类似。
区别在于:
cin.get()当输入的字符串超长时,不会引起cin函数的错误,后面的cin操作会继续执行,只是直接从缓冲区中取数据。但是cin.getline()当输入超长时,会引起cin函数的错误,后面的cin操作将不再执行。