程序不仅需要把内容显示到屏幕上,很多时候还需要从键盘读取用户输入的数据,比如登录时输入账号、结账时输入购买数量。在 C++ 中,最常用的输入工具就是 std::cin。
用一句话概括,std::cin 的作用就是:通过键盘输入内容,来给某一个变量赋值。其中,cin 是英文 “character input(字符输入)” 的缩写。
std::cin 基本输入
在 C++ 中,使用 std::cin 可以把用户在终端敲入的数据保存到指定的变量中。与上一节学习的 std::cout 一样,使用 std::cin 之前也必须在代码开头写上 #include <iostream> 来引入标准输入输出头文件。
语法:
std::cin >> 变量名;说明:
std::cin 表示标准输入,默认对应的就是键盘,而 >> 叫做 “流提取运算符”。大家不用死记这个名称,和输出语句的箭头方向放在一起对比就很容易记住:
- std::cout <<:箭头朝左,表示把右边的数据顺着箭头输送给
std::cout显示到屏幕上。 - std::cin >>:箭头朝右,表示从
std::cin取出用户输入的数据,顺着箭头装进右边的变量里。
示例 1:输入一个整数
#include <iostream>
int main() {
int count = 0;
std::cin >> count;
std::cout << "count = " << count << '\n';
return 0;
}实际运行时,输入 “25” 后得到的结果如下。
25
count = 25分析:
当程序执行到 std::cin >> count; 时,控制台窗口会出现一个闪烁的光标,暂停下来等待我们从键盘输入内容。当我们在键盘上敲入 25 并按下 Enter 键后,整数 25 就会赋给变量 count,覆盖原来的初始值 0。
随后 std::cout 把结果打印出来。因此,上面运行结果中的第一行 25 是我们在键盘敲入的内容,第二行 count = 25 则是程序输出的结果。
细心的小伙伴应该发现了,上面这个例子一运行,控制台只有一个光标在闪,却没有告诉用户应该输入什么。在实际开发中,调用 std::cin 之前最好先打印一句提示文字,这是一个非常好的编程习惯。请看下面例子。
示例 2:输入前添加提示文字
#include <iostream>
int main() {
int count = 0;
std::cout << "请输入商品数量:";
std::cin >> count;
std::cout << "你输入的数量是:" << count << '\n';
return 0;
}实际运行时,输入 “25” 后得到的结果如下。
请输入商品数量:25
你输入的数量是:25分析:
std::cout << "请输入商品数量:"; 先在屏幕上打印一句提示文字。注意这里提示语末尾没有加换行符 \n,这样用户在键盘敲入的 25 就能紧跟在冒号后面显示,交互体验更加自然直观。
注意
看清箭头方向:std::cin 后面跟的是朝右的双尖括号 >>,千万不要和 std::cout 的 << 写反了。
右边必须写普通变量名:std::cin >> 右边必须写可修改的变量名,不能写具体数字或 const常量。学过 C 语言的小伙伴也要留意,这里直接写变量名即可,不需要像 scanf() 那样加取地址符 &。
连续输入多个值
如果需要连续读取多个数据,我们既可以分成多条 std::cin 语句来写,也可以在同一条语句中连续使用多个 >>。
语法:
std::cin >> 变量1 >> 变量2 >> 变量3;说明:
当一条语句中包含多个 >> 时,std::cin 会按照从左到右的顺序,将用户输入的数据依次存入对应的变量中。我们在终端输入的多项数据之间,可以使用一个或多个空格、Tab 键或者回车换行隔开。
示例 3:连续输入两个整数
#include <iostream>
int main() {
int a = 0;
int b = 0;
std::cout << "请输入两个整数:";
std::cin >> a >> b;
std::cout << "两数之和为:" << a + b << '\n';
return 0;
}实际运行时,输入 “10 20” 后得到的结果如下。
请输入两个整数:10 20
两数之和为:30分析:
std::cin >> a >> b; 会先读取第 1 个整数保存到变量 a,再跳过中间的空格,读取第 2 个整数保存到变量 b。输入时既可以敲入 10 20 后按一次 Enter 键,也可以每敲一个数字按一次 Enter 键分成两行输入。
对于这个例子来说,下面 2 种方式是等价的:
// 方式 1
std::cin >> a;
std::cin >> b;
// 方式 2
std::cin >> a >> b;在实际开发中,如果只有两三个紧密相关的数据,连续写在一行比较省事。如果每个数据都需要单独配一句提示语,比如先提示输入账号、再提示输入密码,那么分开写成多条 std::cin 语句会更清晰。
读取不同类型的数据
std::cin 并不是只能读取整数。对于前面学过的 int、double、char 等基础数据类型,std::cin 都会自动根据右边变量的类型来解析输入内容。
示例 4:读取多种类型的数据
#include <iostream>
int main() {
int count = 0;
double price = 0.0;
char level = 'A';
std::cout << "请依次输入数量、单价和等级:";
std::cin >> count >> price >> level;
std::cout << count << ' ' << price << ' ' << level << '\n';
return 0;
}实际运行时,依次输入 “5 19.8 B” 后得到的结果如下。
请依次输入数量、单价和等级:5 19.8 B
5 19.8 B分析:
在这个例子中,我们依次定义了整型、浮点型和字符型 3 个变量。执行输入时,std::cin 会按各自的类型自动转换:先将整数 5 存入 count,再将小数 19.8 存入 price,最后跳过空格将字符 'B' 存入 level。
常见输入边界问题
在日常使用 std::cin 读取键盘输入时,有 2 个初学者很容易碰到的特殊情况,下面我们结合示例具体来看。
1. 输入内容与类型不匹配
虽然 std::cin 能自动识别变量类型,但前提是我们敲入的内容必须符合该类型的格式。如果变量是 int 整数类型,而我们在键盘上敲入了英文字母 "abc",就会导致读取失败。
示例 5:输入类型不匹配
#include <iostream>
int main() {
int count = 25;
std::cout << "请输入商品数量:";
std::cin >> count;
std::cout << "count 的值为:" << count << '\n';
return 0;
}实际运行时,输入 “abc” 后得到的结果如下。
请输入商品数量:abc
count 的值为:0分析:
从运行结果可以看出,变量 count 原本的初始值是 25,但输入 “abc” 后却变成了 0。这是因为英文字母没法转换成整数,本次读取直接失败:在现代 C++ 中,读取失败会把 count 改写成 0,同时 std::cin 自身进入错误状态,排在后面的其他输入语句也会直接跳过。
还有一种常见情况:如果向 int 变量输入小数 3.14,std::cin 只会读走前面的整数部分 3 存入变量,一遇到小数点 . 就停下来,剩下的 .14 会继续留在内存等候区里干扰后续读取。因此大家在初学阶段测试程序时,记得按提示输入对应格式的数据即可。
2. 遇到空格自动截断
当我们在键盘上敲完数据并按下回车后,这些字符并不会立刻直接塞进变量里,而是先存放在内存里一块叫 “输入缓冲区” 的临时等候区中,std::cin >> 每次都会按顺序从这块等候区里取走数据。
由于 std::cin >> 把空格、制表符和换行符都当成了 “数据分隔符”,一旦输入的内容中间包含空格,当前这条语句读到空格处就会停下来,认为这一项已经读完了。而空格后面的内容会继续留在输入缓冲区里,直接留给下一条 std::cin >> 取走。下面我们来看一个例子。
示例 6:空格截断与缓冲区残留
#include <iostream>
int main() {
int first = 0;
int second = 0;
std::cout << "请输入第 1 个整数:";
std::cin >> first;
std::cout << "请输入第 2 个整数:";
std::cin >> second;
std::cout << "first = " << first << '\n';
std::cout << "second = " << second << '\n';
return 0;
}实际运行时,在第一次提示处直接输入 “10 20” 后得到的结果如下。
请输入第 1 个整数:10 20
请输入第 2 个整数:first = 10
second = 20分析:
为什么还没有等我们输入第二个整数,程序就直接把结果打印出来了呢?这是因为我们在第一次提示处一口气输入了 “10 20”,std::cin >> first; 读到中间的空格就停了下来,只把前面的 10 存进了 first,而空格后面的 20 依然留在输入缓冲区里。
紧接着程序打印出 "请输入第 2 个整数:",往下执行到 std::cin >> second; 时,发现缓冲区里现成就有 20。于是它不会再停下来等待我们敲键盘和按回车,而是直接取走 20 存进 second,紧贴在提示语后面就把 first = 10 打印出来了。
按照同样的道理,以后如果需要读取包含空格的一整行文字,比如一句带空格的英文,也不能直接使用 std::cin >>,而要使用专门的 getline() 函数按行读取。
