输入输出--I/O流【C++提升】

news2024/10/20 9:20:11

1.1基础知识:

在C++中,输入输出(IO)流是通过标准库中的 <iostream> 头文件来处理的。C++ 提供了几种基本的输入输出流类,最常用的有以下几种:

  1. std::cin:用于输入。
  2. std::cout:用于输出。
  3. std::cerr:用于输出错误信息(无缓冲)。
  4. std::clog:用于输出日志信息(缓冲)。

基本使用示例

下面是一个简单的例子,展示如何使用这些 IO 流进行输入输出操作。

#include <iostream>  
#include <string>  

int main() {  
    std::string name;  
    int age;  

    // 输出提示信息  
    std::cout << "请输入您的名字: ";  
    std::cin >> name; // 从标准输入读取名字  

    std::cout << "请输入您的年龄: ";  
    std::cin >> age; // 从标准输入读取年龄  

    // 输出结果  
    std::cout << "你好, " << name << "!你今年 " << age << " 岁。" << std::endl;  

    return 0;  
}

详细说明

  • 输入: 使用 std::cin 时,可以用 >> 运算符来读取不同类型的数据。默认情况下,它会忽略空白字符(空格、换行符等),直到遇到下一个有效的输入。

  • 输出: 使用 std::cout 进行输出时,可以用 << 运算符将多个数据连接在一起,可以很方便地输出多个变量及文本。

  • 错误输出std::cerr 和 std::clog 都用于输出错误信息,区别在于 std::cerr 是无缓冲的,意味着内容会立即输出,而 std::clog 是有缓冲的,可能会延迟输出。

注意事项

  1. 输入输出通常是在控制台进行的,要保证控制台能够接收和显示中文字符,可能需要设置locale。
  2. 使用 std::endl 时,它会在输出流中插入一个换行符,并刷新输出缓冲区。如果只需要换行,可以使用 \n,这样会提高效率,因为不一定每次都需要刷新。

1.2高级特性:

自定义输出格式

C++ 提供了多种方式来控制输出格式。你可以使用格式化标志和流操作符来改变输出格式。

#include <iostream>  
#include <iomanip> // 用于 std::setprecision 和 std::fixed  

int main() {  
    double number = 123.456789;  
    std::cout << std::fixed << std::setprecision(2) << number << std::endl; // 输出 123.46  
    return 0;  
}

 流状态管理

C++ 允许你检查和管理流的状态。你可以检查流是否处于有效状态,是否发生了错误,是否到达文件结束等。

#include <iostream>  
#include <fstream>  

int main() {  
    std::ifstream inFile("test.txt");  
    
    if (!inFile) {  
        std::cerr << "无法打开文件。" << std::endl;  
        return 1;  
    }  

    std::string line;  
    while (std::getline(inFile, line)) {  
        std::cout << line << std::endl;  
    }  

    if (inFile.eof()) {  
        std::cout << "到达文件结束。" << std::endl;  
    }  

    if (inFile.fail()) {  
        std::cout << "读取时发生错误。" << std::endl;  
    }  

    inFile.close();  
    return 0;  
}

流操作符的重载

你可以通过重载 << 和 >> 运算符来自定义对象的输入输出。

#include <iostream>  
#include <string>  

class Person {  
public:  
    std::string name;  
    int age;  

    // 重载 << 运算符  
    friend std::ostream& operator<<(std::ostream& os, const Person& p) {  
        return os << p.name << " " << p.age;  
    }  

    // 重载 >> 运算符  
    friend std::istream& operator>>(std::istream& is, Person& p) {  
        return is >> p.name >> p.age;  
    }  
};  

int main() {  
    Person p{"Alice", 30};  
    std::cout << p << std::endl; // 输出:Alice 30  

    Person p2;  
    std::cin >> p2; // 输入格式:<名字> <年龄>  
    std::cout << p2 << std::endl;   

    return 0;  
}

文件流异常处理

通过设置文件流的异常标志,可以更好地管理文件操作中的错误。

#include <iostream>  
#include <fstream>  

int main() {  
    std::ifstream inFile;  
    inFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); // 设置异常标志  

    try {  
        inFile.open("nonexistent.txt"); // 尝试打开不存在的文件  
    } catch (const std::ifstream::failure& e) {  
        std::cerr << "异常: " << e.what() << std::endl;  
    }  

    return 0;  
}

使用字符串流

C++ 还提供了 std::ostringstream 和 std::istringstream 类,可以在内存中进行字符串流操作。

#include <iostream>  
#include <sstream>  

int main() {  
    std::ostringstream oss; // 输出字符串流  
    oss << "Hello, " << "World! " << 2023;  

    std::string str = oss.str(); // 获取字符串  
    std::cout << str << std::endl; // 输出:Hello, World! 2023  

    std::istringstream iss(str); // 输入字符串流  
    std::string word;  
    while (iss >> word) { // 从字符串中读取单词  
        std::cout << word << std::endl;  
    }  

    return 0;  
}

文件缓冲管理

可以使用 std::ifstream 和 std::ofstream 的成员函数 rdbuf(),进行流缓冲区的操作。例如,你可以直接操作底层缓冲区,或者在特定情况下改变缓冲方式。

#include <iostream>  
#include <fstream>  

int main() {  
    std::ofstream outFile("example.txt");  
    
    // 手动设置缓冲区  
    std::streambuf* originalBuf = std::cout.rdbuf(outFile.rdbuf());  
    
    std::cout << "这行将写入文件 example.txt" << std::endl;  

    // 恢复原来的缓冲区  
    std::cout.rdbuf(originalBuf);  
    std::cout << "这行将写入控制台" << std::endl;  
    
    return 0;  
}

使用标准库算法与流结合

可以将标准库算法与输入输出流结合使用,例如.sort()std::copy() 等,可以更加高效地处理数据。

#include <iostream>  
#include <vector>  
#include <algorithm>  
#include <iterator>  

int main() {  
    std::vector<int> numbers = {5, 3, 4, 1, 2};  

    std::sort(numbers.begin(), numbers.end());  

    std::cout << "排序后的数字: ";  
    std::copy(numbers.begin(), numbers.end(), std::ostream_iterator<int>(std::cout, " "));  
    std::cout << std::endl;  

    return 0;  
}

 2.1文件操作:

在C++中,除了标准输入输出流(如std::cinstd::cout)外,文件输入输出也是常用的功能。可以通过标准库中的 <fstream> 头文件来处理文件的读取和写入。

文件操作基础

C++ 提供了以下几个主要的文件流类:

  1. std::ifstream:输入文件流,用于从文件中读取数据。
  2. std::ofstream:输出文件流,用于向文件中写入数据。
  3. std::fstream:文件流,可以同时用于读取和写入操作。

基本使用示例

以下是一个简单的示例,展示如何使用这几个类进行文件操作。

写入文件:

#include <iostream>  
#include <fstream>  
#include <string>  

int main() {  
    std::ofstream outFile("output.txt"); // 创建输出文件流  

    if (!outFile) { // 检查文件是否成功打开  
        std::cerr << "无法打开文件进行写入。" << std::endl;  
        return 1;  
    }  

    outFile << "这是一行文本。\n";  
    outFile << "这是文件中的第二行。" << std::endl;  

    outFile.close(); // 关闭文件流  
    return 0;  
}

 读取文件:

#include <iostream>  
#include <fstream>  
#include <string>  

int main() {  
    std::ifstream inFile("output.txt"); // 创建输入文件流  

    if (!inFile) { // 检查文件是否成功打开  
        std::cerr << "无法打开文件进行读取。" << std::endl;  
        return 1;  
    }  

    std::string line;  
    while (std::getline(inFile, line)) { // 逐行读取文件  
        std::cout << line << std::endl; // 输出到控制台  
    }  

    inFile.close(); // 关闭文件流  
    return 0;  
}

2.2高级特性:

文件打开模式:

可以指定打开文件的方式,如只读、只写、追加等。可以通过组合打开模式标志来实现,例如:

std::ofstream outFile("output.txt", std::ios::app); // 追加模式

 常用的模式标志有:

  • std::ios::in:打开文件用于读取。
  • std::ios::out:打开文件用于写入。
  • std::ios::app:以追加方式打开文件。
  • std::ios::trunc:打开文件时,如果文件存在,则先清空文件。
  • std::ios::binary:以二进制模式打开文件。

异常处理:

可以使用异常机制来处理文件操作中的错误。通过在文件流中设置异常标志:

std::ifstream inFile("somefile.txt");  
inFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);

 这将使得在文件打开或读取失败时抛出异常。

二进制文件的读写:

使用 std::ios::binary 打开文件,可以进行二进制数据的读写操作。例如,写入和读取基本数据类型或对象(如结构体)。

对象序列化:

可以通过重载 << 和 >> 运算符来实现自定义对象的输入输出。

class Person {  
public:  
    std::string name;  
    int age;  

    friend std::ostream& operator<<(std::ostream& os, const Person& p) {  
        os << p.name << " " << p.age;  
        return os;  
    }  

    friend std::istream& operator>>(std::istream& is, Person& p) {  
        is >> p.name >> p.age;  
        return is;  
    }  
};

3.0模拟实现:

模拟目标:

我们将创建一个名为 MyStream 的类,模拟 C++ 的输入输出流。这个类将支持字符串的读取和写入,并维护一个内部缓冲区。

代码示例: 

#include <iostream>  
#include <string>  
#include <sstream>  

class MyStream {  
private:  
    std::string buffer;      // 内部缓冲区  
    size_t position;         // 当前读取位置  

public:  
    MyStream() : position(0) {}  

    // 写入字符串到缓冲区  
    void write(const std::string& str) {  
        buffer += str;       // 追加字符串到缓冲区  
    }  

    // 从缓冲区读取字符串  
    bool read(std::string& outStr) {  
        if (position >= buffer.size()) {  
            return false; // 没有更多数据可读  
        }  

        // 查找下一个空格  
        size_t nextSpace = buffer.find(' ', position);  
        if (nextSpace == std::string::npos) {  
            nextSpace = buffer.size(); // 到达字符串末尾  
        }  

        // 提取子字符串  
        outStr = buffer.substr(position, nextSpace - position);  
        position = nextSpace + 1; // 更新当前位置  

        return true; // 成功读取  
    }  

    // 清空缓冲区  
    void clear() {  
        buffer.clear();  
        position = 0;  
    }  

    // 打印当前缓冲区的内容  
    void print() const {  
        std::cout << "Buffer: " << buffer << ", Position: " << position << std::endl;  
    }  
};  

int main() {  
    MyStream myStream;  

    // 写入数据到自定义流  
    myStream.write("Hello World from MyStream");  
    myStream.print();  

    // 读取数据  
    std::string word;  
    while (myStream.read(word)) {  
        std::cout << "Read: " << word << std::endl;  
    }  

    // 再次写入新的数据  
    myStream.write("Another line");  
    myStream.print();  

    // 在读取新数据之前清空流  
    myStream.clear();  
    myStream.print();  

    // 再次写入数据  
    myStream.write("After clearing the buffer");  
    myStream.print();  

    // 读取新数据  
    while (myStream.read(word)) {  
        std::cout << "Read: " << word << std::endl;  
    }  

    return 0;  
}
  1. MyStream 类:

    • buffer 用于保存写入的数据。
    • position 用于记录当前读取的位置。
    • write 方法用于向缓冲区添加字符串。
    • read 方法用于从缓冲区读取下一个词并更新读取位置。如果没有可读的数据,返回 false
    • clear 方法用于清空缓冲区和重置位置。
    • print 方法用于打印当前的缓冲区内容和位置。
  2. main 函数:

    • 创建 MyStream 对象并写入示例字符串。
    • 读取缓冲区中的单词并打印。
    • 清空缓冲区后再次写入并读取。

尽管这只是一个基础示例,但它揭示了流机制的基本概念,如缓冲、读取位置和字符串处理。


感谢大家!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2219187.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用WPF写一个简单的开关控件

<Window x:Class"WPF练习.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"http://schemas.microsoft.com/expression/blend/2008"xm…

适用于 vue react Es6 jQuery 等等的组织架构图(组织结构图)

我这里找的是 OrgChart 插件; 地址: GitHub - dabeng/OrgChart: Its a simple and direct organization chart plugin. Anytime you want a tree-like chart, you can turn to OrgChart. 这里面能满足你对组织架构图的一切需求! ! ! 例: 按需加载 / 拖拽 / 编辑 / 自定义 / …

【玉米病害识别】Python+卷积神经网络算法+人工智能+深度学习+计算机课设项目+TensorFlow+模型训练

一、介绍 玉米病害识别系统&#xff0c;本系统使用Python作为主要开发语言&#xff0c;通过收集了8种常见的玉米叶部病害图片数据集&#xff08;‘矮花叶病’, ‘健康’, ‘灰斑病一般’, ‘灰斑病严重’, ‘锈病一般’, ‘锈病严重’, ‘叶斑病一般’, ‘叶斑病严重’&#x…

使用JMeter进行Spring Boot接口的压力测试

使用 Apache JMeter 对接口进行压力测试是一个相对简单的过程。以下是详细的步骤&#xff0c;包括安装、配置和执行测试计划。 1. 下载和安装 JMeter 下载 JMeter 从 JMeter 官方网站https://jmeter.apache.org/download_jmeter.cgi 下载最新版本的 JMeter。 解压缩 将下载的 …

【AIGC】ChatGPT与人类理解力的共鸣:人机交互中的心智理论(ToM)探索

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;心智理论(Theory of Mind,ToM)心智理论在心理学与神经科学中的重要性心智理论对理解同理心、道德判断和社交技能的重要性结论 &#x1f4af;乌得勒支大学研究对ChatGPT-4…

基于python+dj+mysql的音乐推荐系统网页设计

音乐网站开发 如果你在学Python&#xff0c;需相关的【配套资料工具】作为研究[doge][脱单doge] 可以后台✉私信up主&#xff0c;发送&#x1f449;关键词【音乐】 本章以音乐网站项目为例&#xff0c;介绍Django在实际项目开发中的应用&#xff0c;该网站共分为6个功能模块分…

使用开源的 Vue 移动端表单设计器创建表单

FcDesigner Vant 版是一款基于 Vue3.0 的移动端低代码可视化表单设计器工具&#xff0c;通过数据驱动表单渲染。可以通过拖拽的方式快速创建表单&#xff0c;提高开发者对表单的开发效率&#xff0c;节省开发者的时间。 源码下载 | 演示地址 | 帮助文档 本项目采用 Vue3.0 和 …

Elasticsearch基本使用及介绍

Elasticsearch 1. 关于各种数据库的使用 关于MySQL&#xff1a;是关系型数据库&#xff0c;能清楚的表示数据之间的关系&#xff0c;并且&#xff0c;是基于磁盘存储的&#xff0c;可以使用相对较低的成本存储大量的数据 关于Redis&#xff1a;是基于K-V结构的在内存中读写数…

屏蔽小米电视广告的方法

小米电视那个广告&#xff0c;太多&#xff0c;时间太长&#xff0c;影响观看感受&#xff0c;经过处理&#xff0c;成功屏蔽了小米电视的广告&#xff0c;提升了观影体验。 手动添加AD域名到 hosts 列表 小米(红米)电视关闭开机AD屏蔽hosts方法。 在路由器的hosts中配置。 …

信息安全工程师(58)网络安全漏洞处置技术与应用

前言 网络安全漏洞处置技术与应用是一个复杂而关键的领域&#xff0c;它涉及漏洞的发现、评估、修补以及后续的监控与防范等多个环节。 一、网络安全漏洞发现技术 网络安全漏洞发现技术是漏洞处置的首要步骤&#xff0c;它旨在通过各种手段识别出网络系统中存在的潜在漏洞。这些…

Unity开发Hololens项目

Unity打包Hololens设备 目录Visual Studio2019 / Visual Studio2022 远端部署设置Visual Studio2019 / Visual Studio2022 USB部署设置Hololens设备如何查找自身IPHololens设备门户Unity工程内的打包设置 目录 记录下自己做MR相关&#xff1a;Unity和HoloLens设备的历程。 Vi…

Vue学习笔记 Class绑定 Style绑定 侦听器 表单输入绑定 模板引用 组件组成 组件嵌套关系

文章目录 Class绑定绑定对象绑定数组注意事项 style绑定绑定对象代码效果展示 绑定数组 侦听器注意的点代码效果 表单输入绑定示例代码效果展示 修饰符.lazy.number.trim 模板引用组件组成组件组成结构引入组件步骤style中的scoped作用 组件嵌套关系 Class绑定 绑定对象 绑定数…

论文精读:PRL 交变磁MnTe中的手性分裂磁振子

DOI: 10.1103/PhysRevLett.133.156702 摘要节选 与电子带的自旋分裂一样&#xff0c;预测交变磁体中的磁振子带也表现出交替的手性分裂。本文通过对α-MnTe进行非弹性中子散射&#xff08;INS&#xff09;&#xff0c;直接观察到α-MnTe的磁振子分裂现象。磁振子的简并解除可以…

【计算机网络 - 基础问题】每日 3 题(四十七)

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?typeblog &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞…

硬盘格式化后能恢复数据吗?4款好用的数据恢复软件,格式化后也能安心

咱们今天来谈谈一个挺烦人的问题——硬盘格式化后能恢复数据吗&#xff1f;别担心&#xff0c;能的&#xff01;只要你用对方法&#xff0c;就算硬盘被清空了&#xff0c;那些重要文件还是能找回来的。下面&#xff0c;我就给你们介绍几款超给力的数据恢复软件&#xff0c;让你…

Axure重要元件三——中继器修改数据

亲爱的小伙伴&#xff0c;在您浏览之前&#xff0c;烦请关注一下&#xff0c;在此深表感谢&#xff01; 课程主题&#xff1a;中继器修改数据 主要内容&#xff1a;显示编辑内容、表格赋值、修改数据 应用场景&#xff1a;更新行、表单数据行修改 案例展示&#xff1a; 正文…

玫瑰花HTML源码

HTML源码 <pre id"tiresult" style"font-size: 9px; background-color: #000000; font-weight: bold; padding: 4px 5px; --fs: 9px;"><b style"color:#000000">0010000100000111101110110111100010000100000100001010111111100110…

【Qt】控件——Qt按钮类控件、常用的按钮类控件、按钮类控件的使用、Push Button、Radio Button、Check Box

文章目录 Qt3. Qt按钮类控件Push ButtonRadio ButtonCheck Box Qt 3. Qt按钮类控件 Push Button 使用 QPushButton 表示一个按钮。当点击按钮时可以触发各种事件。QPushButton 继承自 QAbstractButton。这个类是一个抽象类。是其他按钮的父类。 PushButton和QAbstractButton的…

Flink时间语义和时间窗口

前言 在实际的流计算业务场景中&#xff0c;我们会发现&#xff0c;数据和数据的计算往往都和时间具有相关性。 举几个例子&#xff1a; 直播间右上角通常会显示观看直播的人数&#xff0c;并且这个数字每隔一段时间就会更新一次&#xff0c;比如10秒。电商平台的商品列表&a…

算法笔记day05

目录 1.最小公倍数 2.最长连续的子序列 3.字母收集 1.最小公倍数 求最小公倍数_牛客题霸_牛客网 算法思路&#xff1a; 这就是一道数学题&#xff0c;a,b的最小公倍数 a * b / 最大公约数。 使用辗转相除法&#xff0c;求a&#xff0c;b的最大公约数。 #include <iostre…