Kodewick
第 3 课,共 30 课目录

输入和输出格式

第 3 课,共 30 课 · 第 1 部分 · 起步 · 约 15 分钟

到现在为止,程序里的值都是写死的。std::cin 是输入流:它等用户输入,再把读到的值放进变量。点运行,输入一个数试试;页面上显示的是有人输入 25 时的样子(输入的内容本身不显示)。

main.cpp
1#include <iostream>2 3int main() {4    int age = 0;5    std::cout << "你多大了?\n";6    std::cin >> age;7    std::cout << "你今年 " << age << " 岁\n";8    return 0;9}
输出
你多大了?
你今年 25 岁

std::cin >> age 的箭头朝着变量:值从 cin 流进 age。cout 用 <<,箭头朝着 cout,值流出去。>> 会看变量的类型:age 是 int,它就读一个整数。

一次读几个

和 cout 一样,>> 可以连着写,按顺序放进几个变量。类型不同也没关系:

main.cpp
1#include <iostream>2 3int main() {4    int count = 0;5    double price = 0;6    std::cout << "买几件?单价多少?\n";7    std::cin >> count >> price;8    std::cout << "一共 " << count * price << " 元\n";9    return 0;10}
输出
买几件?单价多少?
一共 59.7 元

用户可以输入 3 19.9 再回车,也可以 3 回车、19.9 回车:>> 会先跳过空格和换行,再去读下一个值。

读到空格就停

>> 也能读 std::string。但它只读一个「词」:跳过前面的空格,读到下一个空格或换行就停。假设用户输入的是 林 小明:

main.cpp
1#include <iostream>2#include <string>3 4int main() {5    std::string name;6    std::cout << "你叫什么名字?\n";7    std::cin >> name;8    std::cout << "你好," << name << "!\n";9    return 0;10}
输出
你叫什么名字?
你好,林!

只读到了 林。空格后面的 小明 还留在输入里,等下一次读。

getline 读一整行

要连空格一起读,用 std::getline(std::cin, s):它把这一行剩下的内容全放进 s,到换行为止(换行本身不要)。

main.cpp
1#include <iostream>2#include <string>3 4int main() {5    std::string name;6    std::cout << "你叫什么名字?\n";7    std::getline(std::cin, name);8    std::cout << "你好," << name << "!\n";9    return 0;10}
输出
你叫什么名字?
你好,林 小明!

getline 也在 <string> 里。读名字、地址、一句话,用它;读数字,用 >>。

cin >> 后面接 getline

先用 >> 读一个数,再用 getline 读一行,会出一个有名的问题。用户输入 30 回车,再输入 林 小明 回车:

main.cpp
1#include <iostream>2#include <string>3 4int main() {5    int age = 0;6    std::string name;7    std::cin >> age;8    std::getline(std::cin, name);9    std::cout << "年龄:" << age << '\n';10    std::cout << "名字:" << name << '\n';11    return 0;12}
输出
年龄:30
名字:

名字是空的。>> 读完 30 就停了,30 后面的那个换行还留在输入里。getline 一上来就碰到它,以为这一行已经结束,读到一个空行。

改法:在 getline 之前加一句 std::cin.ignore();(ignore 是 cin 自己会做的一件事,所以写在 std::cin. 后面),丢掉一个字符,也就是那个换行:

main.cpp
1#include <iostream>2#include <string>3 4int main() {5    int age = 0;6    std::string name;7    std::cin >> age;8    std::cin.ignore();9    std::getline(std::cin, name);10    std::cout << "年龄:" << age << '\n';11    std::cout << "名字:" << name << '\n';12    return 0;13}
输出
年龄:30
名字:林 小明

注意: ignore() 只丢一个字符。用户在 30 后面多打了空格,就丢不干净了。现在记住这个坑在哪儿就够了。

控制小数位

输出的样子也可以控制,工具在 <iomanip> 里。std::setprecision(n) 单独用时,管的是一共显示几位数字;前面加上 std::fixed,它才是「小数点后面几位」:

main.cpp
1#include <iostream>2#include <iomanip>3 4int main() {5    double average = 86.4567;6    std::cout << average << '\n';7    std::cout << std::setprecision(2) << average << '\n';8    std::cout << std::fixed << average << '\n';9    std::cout << 5.0 << '\n';10    return 0;11}
输出
86.4567
86
86.46
5.00

第二行只有两位数字:86。第三行有了 std::fixed,是两位小数 86.46(会四舍五入)。最后一行说明:这两个设置一直有效,后面的 double 都显示两位小数,连 5.0 也成了 5.00。显示价格、平均分,通常就写一次 std::fixed << std::setprecision(2)。

setw 对齐

std::setw(n) 让下一个值至少占 n 格,不够的在左边补空格,数字就能右对齐:

main.cpp
1#include <iostream>2#include <iomanip>3 4int main() {5    std::cout << "苹果" << std::setw(6) << 3 << '\n';6    std::cout << "香蕉" << std::setw(6) << 12 << '\n';7    std::cout << "西瓜" << std::setw(6) << 120 << '\n';8    return 0;9}
输出
苹果     3
香蕉    12
西瓜   120

和 fixed 不同,setw 只管紧跟在它后面的那一个值,每个要对齐的值前面都要写一次。它按字节数算宽度,一个汉字在这里算 3 个,所以别拿它去对齐汉字。

先猜一猜

[ 和 42 之间有几个空格?

1#include <iostream>2#include <iomanip>3 4int main() {5    std::cout << "[" << std::setw(5) << 42 << "]\n";6    return 0;7}

练一练

写好代码,点检查。提示随便看,实在想不出来再看答案。练习里没人输入,要「输入」的值已经写在变量里了。

练习 1

两位小数的价格

让程序显示 价格:3.50。

要显示
价格:3.50
exercise1.cpp
1#include <iostream>2#include <iomanip>3 4int main() {5    double price = 3.5;6    std::cout << "价格:" << price << '\n';7    return 0;8}
输出
点「运行」或按 Ctrl+Enter
练习 2

对齐的分数

用 std::setw(5) 让三个分数右对齐,显示成下面的样子(每个分数占 5 格)。

要显示
数学   95
化学    8
美术  100
exercise2.cpp
1#include <iostream>2#include <iomanip>3 4int main() {5    int math = 95;6    int chem = 8;7    int art = 100;8 9    return 0;10}
输出
点「运行」或按 Ctrl+Enter
练习 3

修好它:少了两位小数

程序本来想显示 总价:12.00,却显示了 总价:12。改好它。

要显示
总价:12.00
exercise3.cpp
1#include <iostream>2#include <iomanip>3 4int main() {5    double total = 4 * 3.0;6    std::cout << std::setprecision(2);7    std::cout << "总价:" << total << '\n';8    return 0;9}
输出
点「运行」或按 Ctrl+Enter

这一课学会了

  • std::cin >> x 从输入读一个值放进 x,按 x 的类型来读;>> 可以连着读几个。
  • >> 会跳过空格和换行;读 std::string 时只读一个词,碰到空格就停。
  • std::getline(std::cin, s) 读一整行,空格也算。
  • cin >> 后面接 getline,会读到剩下的换行;先 std::cin.ignore(); 把它丢掉。
  • <iomanip>:std::fixed << std::setprecision(2) 显示两位小数,之后一直有效。
  • std::setw(n) 让下一个值至少占 n 格,右对齐,只管一个值。