跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
C++算法

C/C++ 输入输出实战:OJ 场景与性能优化

综述由AI生成C/C++ 输入输出是算法竞赛的基础。梳理了 OJ 常见输入模式(单组、多组已知/未知、特殊值结束),讲解了含空格字符串及数字处理的技巧,并对比了 scanf/printf 与 cin/cout 的性能差异及同步优化方法,帮助开发者写出高效健壮的代码。

王者发布于 2026/3/23更新于 2026/5/56 浏览
C/C++ 输入输出实战:OJ 场景与性能优化

C/C++ 输入输出实战:OJ 场景与性能优化

在算法竞赛和工程开发中,输入输出(I/O)是与外部交互的基础。C 和 C++ 提供了强大的 I/O 机制,从简单的 printf/scanf 到 C++ 的流式操作 cin/cout,看似简单,实则暗藏玄机。许多开发者在使用过程中可能会遇到缓冲区问题、格式控制陷阱或性能瓶颈。

本文将结合 OJ(Online Judge)常见场景,梳理输入输出的处理技巧,并深入对比不同 I/O 方式的性能差异。

OJ 题目输入情况汇总

在竞赛环境中,输入模式通常可以归纳为以下几类,掌握这些模式能避免大部分 TLE(超时)或 WA(答案错误)。

单组测试用例

这类题目只包含一组数据,读入后计算并输出即可。

示例:计算 (a+b)/c 的值

#include <iostream>
using namespace std;

int main() {
    int a, b, c;
    cin >> a >> b >> c;
    cout << (a + b) / c << endl;
    return 0;
}

示例:与 7 无关的数

思路:先找出与 7 相关的正整数,然后取反得到无关的正整数。条件包括:被 7 整除、个位是 7、十位是 7。

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    int i = 1, sum = 0;
    while (i <= n) {
        if (i % 7 != 0 && i % 10 != 7 && i / 10 != 7) {
            sum += (i * i);
        }
        i++;
    }
    cout << sum << endl;
    return 0;
}

多组测试用例

测试数据组数已知

题目会首先给出一个整数 n,表示接下来有 n 组数据。

示例:多组输入 a+b II

#include <iostream>
using namespace std;

int main() {
    int n; // 表示数据组数
    cin >> n;
    int a, b;
    while (n--) {
        cin >> a >> b;
        cout << a + b << endl;
    }
    return 0;
}

示例:斐波那契数列

对于范围有限的查询,预处理(打表)往往比每次递归更高效。

#include <iostream>
using namespace std;

int main() {
    int n, a, i;
    int ret[35] = {0, 1, 1};
    for (i = 3; i < 30; i++) {
        ret[i] = ret[i - 1] + ret[i - 2];
    }
    cin >> n;
    while (n--) {
        cin >> a;
        cout << ret[a] << endl;
    }
    return 0;
}
测试数据组未知

没有明确的组数提示,需要判断输入是否结束。常用方法是利用流的状态作为循环条件。

示例:多组输入 a+b

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) {
        cout << a + b << endl;
    }
    return 0;
}

原理:cin >> a >> b 返回流对象的引用。如果读取成功,流状态为真;如果遇到文件结束符或类型不匹配,流状态为假,循环终止。

特殊值结束测试数据

当输入中包含特定的终止标记(如 0 0 或特定字符)时,需在循环内判断。

示例:多组数据 a+b III

#include <iostream>
using namespace std;

int main() {
    int a = 0, b = 0;
    // 逗号表达式,只有当 a 和 b 都不为 0 时才继续
    while (cin >> a >> b, a && b) {
        cout << a + b << endl;
    }
    return 0;
}

输入时特殊技巧

含空格字符串的处理

读取包含空格的字符串时,cin 默认会在空格处停止。此时可以使用 getline 一次性读取整行,或者根据需求按单词处理。

练习:统计数字字符个数

方法一:按行读取

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s;
    getline(cin, s);
    int ret = 0;
    for (auto ch : s) {
        if (ch >= '0' && ch <= '9') {
            ret++;
        }
    }
    cout << ret << endl;
    return 0;
}

方法二:按单词读取

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s;
    int cnt = 0;
    while (cin >> s) {
        for (auto c : s) {
            if (c >= '0' && c <= '9') cnt++;
        }
    }
    cout << cnt << endl;
    return 0;
}

数字的特殊处理

输入的数字既可以是整型,也可以是字符串。根据题目要求选择解析方式。

练习:小乐乐改数字

方法一:当做整数读取

通过 % 10 获取末位,/ 10 去掉末位,逐位处理。

#include <iostream>
#include <cmath>
using namespace std;

int main() {
    int n;
    int i = 0, ret = 0;
    cin >> n;
    while (n) {
        if (n % 10 % 2 == 1) {
            ret += pow(10, i);
        }
        n /= 10;
        i++;
    }
    cout << ret << endl;
    return 0;
}

方法二:当做字符串处理

利用 ASCII 码特性,偶数位对应偶数,奇数位对应奇数。

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s;
    cin >> s;
    for (int i = 0; i < s.size(); i++) {
        if (s[i] % 2) {
            s[i] = '1';
        } else {
            s[i] = '0';
        }
    }
    cout << stoi(s) << endl;
    return 0;
}

scanf/printf 和 cin/cout 的对比

scanf/printf 是 C 语言的标准函数,cin/cout 是 C++ 的流对象。两者各有优劣。

格式控制差异

  • scanf/printf:需要手动指定格式字符串,容易出现类型不匹配导致的未定义行为,但格式化输出更精确直观。
  • cin/cout:自动识别类型,不易出错,但在复杂格式输出上不如 printf 灵活。
#include <cstdio>
#include <iostream>
using namespace std;

int main() {
    float a = 3.50;
    double d = 16.50;
    cout << "cout: " << a << " " << d << endl;
    printf("printf: %f %lf\n", a, d);
    return 0;
}

区别:cout 默认忽略多余的小数 0,而 printf 默认打印 6 位小数。

性能差异

在数据量较大时,scanf/printf 通常比 cin/cout 快。这是因为 cin/cout 为了兼容性和安全性,默认开启了同步机制。

性能优化方案

若需使用 cin/cout 但追求高性能,可关闭同步并解除绑定。

ios::sync_with_stdio(false); // 取消 C++ 流与 C 标准库流的同步
cin.tie(0);                  // 取消 cin 与 cout 的绑定

案例演示

以下代码展示了关闭同步前后的性能差异。在百万级数据输入下,优化后的 cin 速度可接近 scanf。

#include <iostream>
#include <ctime>
#include <cstdio>
using namespace std;

const int num = 10000000;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    
    int i, x;
    clock_t t1, t2;
    t1 = clock();
    for (i = 0; i < num; i++) {
        cin >> x;
    }
    t2 = clock();
    cout << "Runtime of cin: " << t2 - t1 << " ms" << endl;
    return 0;
}

总结建议

  • 数据量较小(10^6 以内):cin/cout 足够,代码可读性更好。
  • 数据量极大(10^9 左右):推荐使用 scanf/printf 或优化后的 cin/cout,避免 IO 开销导致超时。
  • 混合使用时:务必注意同步设置,否则可能导致输出顺序错乱。

掌握输入输出的底层机制和陷阱,才能写出健壮高效的代码。从缓冲策略到格式控制,每个细节都可能成为调试时的关键。

目录

  1. C/C++ 输入输出实战:OJ 场景与性能优化
  2. OJ 题目输入情况汇总
  3. 单组测试用例
  4. 多组测试用例
  5. 测试数据组数已知
  6. 测试数据组未知
  7. 特殊值结束测试数据
  8. 输入时特殊技巧
  9. 含空格字符串的处理
  10. 数字的特殊处理
  11. scanf/printf 和 cin/cout 的对比
  12. 格式控制差异
  13. 性能差异
  14. 性能优化方案
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Motrix WebExtension 浏览器扩展配置与使用指南
  • Linux 系统进阶:Git 远程协作与分支管理实战
  • JVM 垃圾回收核心:根可达性、三色标记与 CMS/G1 对比
  • Spring Boot Web 三大核心交互实战:表单、AJAX 与 JSON
  • YOLOv8 C++部署实战:高性能推理引擎实现
  • 使用 ZeroNews 远程管理 OpenClaw Gateway Dashboard
  • 学生如何申请和使用 GitHub Copilot
  • C++ STL 进阶:unordered_set 与 unordered_map 模拟实现
  • Web3j 快速搭建 Java 区块链应用配置指南
  • 微信小程序 WebView 与 H5 页面双向通信实战指南
  • VSCode 远程 SSH 连接下 Copilot 使用 Claude 模型及代理配置问题
  • 2026 年 AI 编程助手组合使用心得
  • Andrej Karpathy 解析人工智能未来发展策略
  • 无人机 Remote ID Beacon 帧结构深度解析
  • JDK 17 安装与环境配置实战指南
  • 主流前端动画库实战指南:GSAP、Lottie、Swiper 与 AOS 对比
  • C++ 继承中的同名成员隐藏规则详解
  • 基于 LLama-Factory 微调大模型生成合规隐私政策
  • 双指针算法技巧全场景拆解:从数组操作到环检测
  • Spring Boot 2.7.18 版本概览与升级建议

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online