C++ std::cin
C++ std::cin
- 相关概念
- 使用
- 1. 一个常见的使用场景:
- 2. 用于静态对象的构造和析构函数中,访问标准输入/输出流是安全的。
- 3. 作为 *while* 语句的条件
- 4. 配合 *get*、*getline* 使用
相关概念
- istream 一个class,提供输入操作。
- cin 一个 istream 对象,用于从标准输入读取数据。
- >> 运算符,用于从一个 istream 对象读取输入数据。
【注】cin 中的字符 ‘c’ 指 ‘character’,“cin” 就是 ‘character input’ 的意思
std::cin 是一个全局对象,与标准C输入流 stdin 关联。
使用
1. 一个常见的使用场景:
int main() {
/*
...
*/
int ival;
cin >> ival;
/*
...
*/
return 0;
}
支持多类型输入:
int main() {
int iage;
std::string strname;
std::cout << "Enter 'name' and 'age': ";
std::cin >> strname >> iage;
std::cout << "Name: " << strname
<< "\t" << "Age: " << iage << std::endl;
return 0;
}
因为 cin 会跳过空白字符比如 空格、回车,所以虽然在同一行输入了名字和类型,但是它们会分开保存到对应的变量中:
2. 用于静态对象的构造和析构函数中,访问标准输入/输出流是安全的。
#include<iostream>
struct UserDefinedStruct{
int m_ival;
UserDefinedStruct() {
std::cout << "Enter ival: ";
std::cin >> m_ival;
}
};
// 定义一个静态对象
UserDefinedStruct uds;
int main() {
std::cout << "uds.m_ival is "
<< uds.m_ival
<< std::endl;
return 0;
}
3. 作为 while 语句的条件
int ival;
while(cin >> ival) {
/*
...
*/
}
cin 操作的对象是一个 int 变量,输入运算符期待读取一个 int,当输入不符合期待时(比如输入字符 ‘a’),cin 就会进入错误状态,因此跳出循环。
那么 cin >> ival 为什么可以作为 while 的条件?
查看操作符 >> 的函数定义:
basic_istream& operator>>( int& value );
也就是说,basic_istream 在特定上下文中是可以隐式转换为一个 bool 值。我们知道 IO 操作的一个问题就是它有可能会产生问题。。。因此 IO 类中定义了一些函数和标志以便于使用者访问和操纵流的条件状态,参看 C++ Primer 第五版:
cin >> ival 之所以可以作为 while 语句的条件,是因为 istream 重载了 operator bool,而 operator bool 会在 fail() 为 false 并且还处于 IO ready state 的时候返回 true。
当 cin >> ival 遇到键入的 ‘a’ 时,因为 ‘a’ 并不是理想的输入,failbit 置位,又因为是在 while 的条件中,这是一个 bool 语境,因此调用了 operator bool, 而 operator bool 中又调用了 fail(),因为 fail() 返回 true,所以 operator bool 返回 false。。。因此退出了循环(为什么不调用 good() 呢。。。)
这个转换是隐式的,咋一看会很迷惑。
前面的例子都是通过 cin 搭配操作符 << 来使用的,外部输入的数据被保存在 cin 的缓冲区中,通过操作符 “<<” 把数据从 cin 中提取出来。操作符 >> 表现为带格式的输入。
在不带格式的输入场景下,可以使用 get 或者 getline。
4. 配合 get、getline 使用
cin 和 get 或者 getline 的组合使用方式十分相似:
// 程序 1
#define MAX_LEN 20
int main() {
char ch[MAX_LEN];
std::cout << "Enter: ";
std::cin.get(ch, MAX_LEN);
std::cout << "Entered: " << std::endl;
// 这里用于输出计数
for(int i = 0; i != 4; ++i) {
for (int j = 0; j != 10; ++j) {
std::cout << j;
}
}
std::cout << '\n';
std::cout << ch;
return 0;
}
输入字符串在长度限制内:
输入字符串超出长度限制:
// 程序 2
#include<iostream>
int main() {
char strname[32];
char straddr[256];
std::cout << "Enter your name: ";
std::cin.getline(strname, 32);
std::cout << "Enter your address: ";
std::cin.getline(straddr, 256);
std::cout << strname << "'s address: " << straddr << std::endl;
return 0;
}
不同的是 get 每次读取一整行并把换行符留在输入队列中,因此在连续多次输入的场景下需要在每次 get 用户输入后再调用一次 get 读取换行符,或者调用 ignore 忽略换行符。而 getline 每次读取一整行后会把换行符丢弃(可以修改程序 2 中的 getline 进行测试)。