【C++ 输入输出】cin、cout、cerr 与格式化输出

1. 为什么需要输入输出?

程序需要与用户"交流":输出 让程序告诉用户结果,输入 让用户告诉程序数据。C++ 通过 <iostream> 库提供了三个最常用的流对象:

对象 含义 默认连接
cin 标准输入 键盘
cout 标准输出 屏幕
cerr 标准错误 屏幕(无缓冲,立即显示)

2. 基本使用:cin、cout、cerr

示例1:读取两个整数并输出它们的和

cpp 复制代码
#include <iostream>
using namespace std;

int main() {
    int a, b;
    cout << "请输入两个整数:";
    cin >> a >> b;
    int sum = a + b;
    cout << "它们的和是:" << sum << endl;
    return 0;
}

运行示例 (假设输入 10 20):

复制代码
请输入两个整数:10 20
它们的和是:30

示例2:使用 cerr 输出错误信息

cpp 复制代码
#include <iostream>
using namespace std;

int main() {
    int age;
    cout << "请输入年龄(0-120):";
    cin >> age;
    if (age < 0 || age > 120) {
        cerr << "错误:年龄超出合理范围!" << endl;
        return 1;   // 非0返回表示异常
    }
    cout << "您的年龄是:" << age << endl;
    return 0;
}

注意cerr 不受输出重定向影响,通常用于错误信息,且不经过缓冲区(立即显示)。

3. 格式化输出(iomanip 库)

C++ 提供了 <iomanip> 头文件中的操作符,用于精细控制输出格式。

3.1 控制整数进制

cpp 复制代码
#include <iostream>
#include <iomanip>
using namespace std;

int main() {
    int num = 255;
    cout << "十进制:" << dec << num << endl;   // 255
    cout << "十六进制:" << hex << num << endl; // ff
    cout << "八进制:" << oct << num << endl;   // 377
    // 恢复十进制
    cout << dec << "恢复十进制:" << num << endl;
    return 0;
}

3.2 控制浮点数精度与格式

cpp 复制代码
#include <iostream>
#include <iomanip>
using namespace std;

int main() {
    double pi = 3.1415926535;
    // 设置固定小数位数(小数点后2位)
    cout << fixed << setprecision(2) << pi << endl; // 3.14
    // 科学计数法
    cout << scientific << setprecision(4) << pi << endl; // 3.1416e+00
    // 恢复默认浮点输出(自动选择)
    cout << defaultfloat << pi << endl;
    return 0;
}

3.3 设置宽度与填充字符

cpp 复制代码
#include <iostream>
#include <iomanip>
using namespace std;

int main() {
    cout << setw(10) << "ID" << setw(10) << "Name" << endl;
    cout << setw(10) << 1001 << setw(10) << "Alice" << endl;
    cout << setw(10) << 1002 << setw(10) << "Bob" << endl;
    // 填充字符改为 '*'
    cout << setfill('*') << setw(10) << 1003 << setw(10) << "Tom" << endl;
    return 0;
}

输出:

复制代码
        ID      Name
      1001     Alice
      1002       Bob
******1003*******Tom

4. 内存模型讲解(浅显易懂)

当我们执行 cin >> acout << "hello" 时,背后发生了什么?来看内存中的"输入输出缓冲区"模型。

复制代码
用户键盘输入 "10 20\n"
       ↓
┌─────────────────────────────────────────┐
│              输入缓冲区 (内存)          │
│  [ '1' , '0' , ' ' , '2' , '0' , '\n' ] │
└─────────────────────────────────────────┘
       ↓  cin 从缓冲区解析整数
       ↓
┌──────────────┐   ┌──────────────┐
│  变量 a (栈) │   │  变量 b (栈) │
│    10        │   │    20        │
└──────────────┘   └──────────────┘
  • 输入缓冲区 :当你在键盘上敲击并按下回车,操作系统把字符序列存入内存中的"输入缓冲区"。cin 从该缓冲区读取并转换成对应类型(比如 int)。
  • 输出缓冲区cout << "结果:" << sum << endl; 先将数据写入"输出缓冲区"(内存中的一块区域),当遇到 endl 或缓冲区满时,系统才真正把内容显示到屏幕(或写入文件)。这样做是为了提高效率(减少慢速 I/O 操作)。

cerr 的特殊性cerr 不经过缓冲区,直接输出到屏幕。这意味着即使程序崩溃,错误信息也能立即显示,不会因为缓冲区没刷新而丢失。

5. 常见错误与避坑

错误写法 问题
cin >> a, b; 逗号不能用于连续输入,应使用 >> 连接:cin >> a >> b;
输入 10 20 但变量类型是 char 类型不匹配,cin 会失败,后续读取无效
cout << setprecision(2) << 3.1415; 没有 fixed 设置的是总有效位数,而不是小数位数
忘记 #include <iomanip> 使用 setwsetprecision 等会编译错误
cerrcout 混用导致顺序奇怪 因为 cout 有缓冲,cerr 无缓冲,可能先显示 cerr 内容再显示 cout

6. 练习题

题目:编写一个程序,要求:

  1. 提示用户输入一个浮点数(例如 123.456789)。
  2. 读取该浮点数,并分别用以下格式输出:
    • 默认格式(保留6位有效数字)
    • 固定小数点后3位
    • 科学计数法(小数点后4位)
  3. 再提示用户输入一个整数(例如 255),分别以十进制、十六进制、八进制输出,每个数占宽8格,用 0 填充前导空白。

示例输入

复制代码
123.456789
255

期望输出

复制代码
默认格式:123.457
固定3位小数:123.457
科学计数法:1.2346e+02
十进制:00000255
十六进制:000000ff
八进制:00000377

提示

  • 使用 fixedscientificsetprecisionsetwsetfillhexoctdec
  • 切换进制后如需恢复十进制,记得使用 dec

上期练习答案

cpp 复制代码
#include <iostream>
using namespace std;

int main() {
    cout << "My name is Alice" << endl;
    cout << "I am learning C++!" << endl;
    return 0;
}

总结 :今天我们学习了 C++ 的标准输入输出 cincoutcerr,掌握了使用 <iomanip> 进行格式化输出的常用方法,并理解了缓冲区在内存中的作用。下一篇文章我们将深入注释与编码风格,继续夯实基础。

快去动手写代码,用格式化输出做出漂亮的报告吧!

相关推荐
小短腿的代码世界7 分钟前
Qt文件系统与IO深度解析:从QFile到异步文件操作
开发语言·qt
智者知已应修善业1 小时前
【51单片机按键调节占空比3位数码管显示】2023-8-24
c++·经验分享·笔记·算法·51单片机
harder3211 小时前
RMP模式的创新突破
开发语言·学习·ios·swift·策略模式
.5481 小时前
## Sorting(排序算法)
python·算法·排序算法
jinanwuhuaguo2 小时前
OpenClaw工程解剖——RAG、向量织构与“记忆宫殿”的索引拓扑学(第十三篇)
android·开发语言·人工智能·kotlin·拓扑学·openclaw
Rust研习社2 小时前
使用 Axum 构建高性能异步 Web 服务
开发语言·前端·网络·后端·http·rust
wuweijianlove2 小时前
算法的平均复杂度建模与性能回归分析的技术7
算法·数据挖掘·回归
子琦啊2 小时前
【算法复习】字符串 | 两个底层直觉,吃透高频题
linux·运维·算法
徐某人..3 小时前
基于i.MX6ULL平台的智能网关系统开发
arm开发·c++·单片机·qt·物联网·学习·arm