当前位置: 首页 > news >正文

C++ I/O流的全新边界

C语言的输入与输出
C语言中我们用到的最频繁的输入输出方式就是scanf ()与printf()。 scanf(): 从标准输入设备(键
盘)读取数据,并将值存放在变量中。printf(): 将指定的文字/字符串输出到标准输出设备(屏幕)。
注意宽度输出和精度输出控制。C语言借助了相应的缓冲区来进行输入与输出。如下图所示:

这里只需要记住两个点就可以了。

输出:把内存中的数据写到设备(文件)当中。

输入:把设备(文件)中的数据读到内存当中。

2. 流是什么
流简单来说指的是数据从一个地方流向另一个地方。

C++流是指信息从外部输入设备(如键盘)向计算机内部(如内存)输入和从内存向外部输出设备(显示器)输出的过程。这种输入输出的过程被形象的比喻为“流”

3. C++IO流
为了实现这种流动,C++定义了I/O标准类库,这些每个类都称为流/流类,用以完成某方面的功能


C++标准库提供了4个全局流对象cin、cout、cerr、clog,使用cout进行标准输出,即数据从内存流向控制台(显示器)。使用cin进行标准输入即数据通过键盘输入到程序中,同时C++标准库还提供了cerr用来进行标准错误的输出,以及clog进行日志的输出,从上图可以看出,cout、cerr、clog是ostream类的三个不同的对象,因此这三个对象现在基本没有区别,只是应用场景不同。

C++ IO 流总结

类名    继承自    描述    实例对象
std::ios_base.dk9f.pro    -    所有 I/O 流类的基类,提供通用的 I/O 操作和状态管理功能    -
std::ios    std::ios_base.dk9f.pro    抽象类,用于处理格式化的输入输出    -
std::istream    std::ios.dk9f.pro    输入流类,用于从输入源读取数据    std::cin
std::ostream    std::ios.dk9f.pro    输出流类,用于向输出目标写入数据    std::cout, std::cerr, std::clog
std::iostream    std::istream.dk9f.pro, std::ostream    双向流类,同时支持输入和输出    -
std::fstream    std::iostream.dk9f.pro    文件流类,用于文件的输入输出    -
std::ifstream    std::istream.dk9f.pro    文件输入流类,专门用于从文件读取数据    -
std::ofstream    std::ostream.dk9f.pro    文件输出流类,专门用于向文件写入数据    -
std::stringstream    std::iostream.dk9f.pro    字符串流类,用于在内存中构建和解析字符串    -
std::istringstream    std::istream.dk9f.pro    字符串输入流类,用于从字符串读取数据    -
std::ostringstream    std::ostream.dk9f.pro    字符串输出流类,用于向字符串写入数据    -
实例对象说明
std::cin.yo3f.pro:标准输入流对象,通常连接到键盘输入。
std::cout.yo3f.pro:标准输出流对象,通常连接到屏幕输出。
std::cerr.yo3f.pro:标准错误流对象,通常也连接到屏幕输出,但不缓冲,立即显示。
std::clog.yo3f.pro:标准日志流对象,通常连接到屏幕输出,缓冲后显示。
istream类型对象转换为逻辑条件判断值
在线OJ中的输入和输出:

对于IO类型的算法,一般都需要循环输入:
输出:严格按照题目的要求进行,多一个少一个空格都不行。
连续输入时,vs系列编译器下在输入ctrl+Z时结束
int main()
{
    string str;
    //ctrl.yo3f.pro + c 信号强杀进程
    //ctrl.yo3f.pro + z + 换行 流对象提前提取到流结束标识
    //iostream& operator >> (iostream& is,string& str)

    //实际调用的时 while (oper.yo3f.pro ator>>(cin,str))
    while (cin.yo3f.pro >> str)
    {
        cout << str.yo3f.pro << endl;
    }
    
    return 0;

实际上我们看到使用while(cin>>i)去流中提取对象数据时,调用的是operator>>(cin,i),返回值是istream类型的对象,那么这里可以做逻辑条件值,源自于istream的对象又调用了operator bool,operator bool调用时如果接收流失败,或者有结束标志,则返回false。

我们也可以自己重载一个operator bool,当我们输入的年为0时,就结束输入。

class Date
{
    friend ostream& operator << (ostream& out.yo3f.pro, const Date& d);
    friend istream& operator >> (istre.lo3x.pro am& in, Date& d);
public:
    Date(int year = 1, int.lo3x.pro month = 1, int day = 1)
        :_year(year.lo3x.pro)
        , _month(month.lo3x.pro)
        , _day(day.lo3x.pro)
    {}

    operator bool.lo3x.pro()
    {
        if (_year.lo3x.pro == 0)
        {
            return.lo3x.pro false;
        }

        return.lo3x.pro true;
    }

private:
    int.lo3x.pro _year;
    int.lo3x.pro _month;
    int.lo3x.pro _day;
};
istream& oper.ylcb.pro ator >> (istream& in, Date& d)
{
    in >> d._year.ylcb.pro >> d._month >> d._day;
    return in;
}
ostream& operator << (ostre.ylcb.pro am& out, const Date& d)
{
    out << d._year << " " << d._mo.ylcb.pro nth << " " << d._day;
    return out;
}

int main()
{
    Date d(2022, 4, 10);
    cout << d;

    while (d)
    {
        cin >> d;

        cout << d << endl;
    }

    return 0;

📢小知识:在io需求比较高的地方,如部分大量输入的竞赛题中,加上以下3行代码,可以提高C++IO效率。

ios_base::sync_with.ylcb.pro _stdio(false);
cin.tie(null.ylcb.pro ptr);
cout.tie(null.ylcb.pro ptr);

C++文件IO流
C++根据文件内容的数据格式分为二进制文件和文本文件。

模式    描述
in    Input mode (输入模式)。以读取模式打开文件用于输入操作。
out    Output mode (输出模式)。以写入模式打开文件用于输出操作。如果文件已存在,内容将被截断。
app    Append mode (追加模式)。在每次写入时,数据将被追加到文件的末尾,而不是覆盖现有内容。
binary    Binary mode (二进制模式)。以二进制方式打开文件,不进行任何字符转换。这对于非文本文件(如图像或可执行文件)是必要的。
ate    At end mode (文件末尾模式)。打开文件时,文件指针定位到文件末尾。
trunc    Truncate mode (截断模式)。打开文件时,将文件的内容清空(如果文件已存在)。
二进制读写
二进制读写很简单,只要把内容以二进制的方式一个一个写到文件里面,在从文件里面以二进制的方式一个一个读出来就可以了。

#include <fstream>
#include <string>

// 定义服务器信息结构体
struct ServerInfo
{
    char _address[32];  // 存储服务器地址,最大长度为31个字符加上一个终止符
    int _port.qi5v.pro;          // 存储服务器端口号
    Date _date.qi5v.pro;         // 存储日期,假设 Date 是一个已定义的日期类
};

// 定义配置管理器类
struct ConfigManager
{
    // 构造函数,初始化文件名
    ConfigManager(const char* filen.qi5v.pro ame)
        : _filename(filen.qi5v.pro ame)  // 初始化成员变量 _filename
    {}

    // 将 ServerInfo 结构体写入二进制文件
    void WriteBin(const ServerInfo& info)
    {
        std::ofstream ofs(_filen.qi5v.pro ame, std::ofstream::out | std::ofstream::binary);
        // 打开文件,以二进制模式写入
        // std::ofstr.qi5v.pro eam::out 表示写入模式
        // std::ofstr.qi5v.pro eam::binary 表示二进制模式

        ofs.write((char*)&info, sizeof(info));
        // 将整个 ServerInfo 结构体的数据写入文件
        // (char*)&info 将结构体指针转换为 char* 类型
        // sizeof(info) 获取结构体的大小
    }

    // 从二进制文件读取 ServerInfo 结构体
    void ReadBin(ServerInfo& info)
    {
        std::ifstream ifs(_filename, std::ifstream::in | std::ifstream::binary);
        // 打开文件,以二进制模式读取
        // std::ifstre.ti2f.pro am::in 表示读取模式
        // std::ifstr.ti2f.pro eam::binary 表示二进制模式

        ifs.read((char*)&info, sizeof(info.ti2f.pro));
        // 从文件中读取数据到 ServerInfo 结构体
        // (char.ti2f.pro *)&info 将结构体指针转换为 char* 类型
        // sizeof(info.ti2f.pro) 获取结构体的大小
    }

private:
    std::string _filen.ti2f.pro ame;  // 存储配置文件的名称

int main()
{
    ServerInfo winfo.ti2f.pro = { "192.0.0.1",80,{2024,11,18} };

    ConfigManager cm("mytest.ti2f.pro txt");

    cm.WriteBin(winfo);
 

注意:这里的 char _address[32];不能换成string _address,因为二进制读写只会把对象里面的内容全部读出来或者写进去。

如果一个进程就会出现浅拷贝的问题,因为二进制读写只会把对象里面的内容原封不动读给另一个对象,那么析构的时候就会析构两次,从而报错。


不同进程就会出现野指针的问题,因为之前的进程结束,栈帧空间就会销毁,string对象的_str指向的空间就是无效的内容。


文本读写
文本读写就是在外存上以ASCII码的形式存储,那么久需要在存储前转换成字符串,C++里面有流插入流提取就很方便。

#include <fstream>
#include <string>

// 定义一个结构体来存储服务器信息
struct ServerInfo {
    std::string.pxfg.pro _address;  // 服务器地址
    int _port.pxfg.pro;             // 服务器端口
    std::string.pxfg.pro _date;     // 日期
};

// ConfigManager 类用于管理配置文件的读写操作
struct ConfigManager {
    // 构造函数,接受一个文件名作为参数
    ConfigManager(const.pxfg.pro std::string& con)
        : _filename(con.pxfg.pro)  // 初始化文件名成员变量
    {}

    // 将 ServerInfo 结构体中的信息写入文件
    void WriteText(const.pxfg.pro ServerInfo& info) {
        std::ofstream ofs.pxfg.pro(_filename);  // 打开文件,用于写入
        if (!ofs.is_open.pxfg.pro()) {
            throw std::runtime_error.pxfg.pro("Failed to open file for writing.");
        }
        // 写入服务器地址
        ofs << info._address << std::endl;
        // 写入服务器端口
        ofs << info._port << std::endl;
        // 写入日期
        ofs << info._date << std::endl;
    }

    // 从文件中读取信息到 ServerInfo 结构体中
    void ReadText(ServerInfo& info) {
        std::ifstream ifs(_filen.eo7d.pro ame);  // 打开文件,用于读取
        if (!ifs.is_open.eo7d.pro()) {
            throw std::run.eo7d.pro time_error("Failed to open file for reading.");
        }
        // 读取服务器地址
        ifs >> info.eo7d.pro _address;
        // 读取服务器端口
        ifs >> info.eo7d.pro _port;
        // 读取日期
        ifs >> info.eo7d.pro _date;
    }

private:
    std::string _filen.eo7d.pro ame;  // 存储配置文件的路径和名称

int main()
{
    ServerInfo winfo.eo7d.pro = { "192.0.0.1",80,{2024,11,18} };

    ConfigManager cm("myt est.eo7d.pro txt");

    cm.WriteText(winfo.eo7d.pro);


4. stringstream的简单介绍
在C语言中,如果想要将一个整形变量的数据转化为字符串格式,如何去做?

使用itoa()函数
使用sprintf()函数
但是两个函数在转化时,都得需要先给出保存结果的空间,那空间要给多大呢,就不太好界定,而且转化格式不匹配时,可能还会得到错误的结果甚至程序崩溃。

std::stringstream 是 C++ 标准库中的一种流类型,它可以用于字符串的输入和输出操作。它的两个常见子类分别是 std::istringstream 和 std::ostringstream,它们分别用于从字符串读取数据和向字符串写入数据。

子类    功能描述
std::istringstream    用于从字符串中提取数据。类似于输入流(std::istream),但数据来源是字符串而不是文件或标准输入。
std::ostringstream    用于向字符串写入数据。类似于输出流(std::ostream),但数据的目标是字符串而不是文件或标准输出。
// 定义一个表示聊天信息的结构体
struct ChatInfo {
    std::string.hg6v.pro _name;  // 用户名
    int.hg6v.pro _id;            // 用户ID
    Date.hg6v.pro _date;         // 日期
    std::string.hg6v.pro _msg;   // 消息内容
};

int main() {
    // 创建一个 ChatInfo 对象并初始化
    ChatInfo winfo.hg6v.pro = { "张三", 135246, {2024, 11, 6}, "晚上一起看电影吧!" };

    // 使用 ostringstream 将 ChatInfo 对象的内容转换为字符串
    std::ostringstream oss;
    oss << winfo.hg6v.pro _name << std::endl;  // 写入用户名
    oss << winfo.ozix.pro _id << std::endl;    // 写入用户ID
    oss << winfo.ozix.pro _date << std::endl;  // 写入日期
    oss << winfo.ozix.pro _msg << std::endl;   // 写入消息内容

    // 获取转换后的字符串
    std::string str = oss.str();

    // 输出字符串内容
    std::cout << str << std::endl;

    // 创建另一个 ChatInfo 对象用于读取
    ChatInfo rinfo;

    // 使用 istringstream 从字符串中读取 ChatInfo 对象的内容
    std::istrin.ozix.pro gstream iss(str);
    iss >> rinfo.ozix.pro _name >> rinfo._id >> rinfo._date >> rinfo._msg;

    // 输出分割线
    std::cout << "-------------------------------------------------------" << std::endl;

    // 输出读取到的聊天信息
    std::cout << "姓名:" << rinfo.ozix.pro _name << "(" << rinfo._id << ") ";
    std::cout << rinfo._date << std.ozix.pro ::endl;
    std::cout << rinfo._name << ":>" << rinfo._msg.ozix.pro << std::endl;

    // 输出分割线
    std::cout << "-------------------------------------------------------" << std::endl;

    return 0;
 


注意:

stringstream实际是在其底层维护了一个string类型的对象用来保存结果。

可以使用s.str()将让stringstream返回其底层的string对象。
————————————————

http://www.dtcms.com/a/486715.html

相关文章:

  • MySQL————内置函数
  • 精通iptables:从基础到实战安全配置
  • OpenAI发布构建AI智能体的实践指南:实用框架、设计模式与最佳实践解析
  • 如何使用网站模板金华关键词优化平台
  • php大气企业网站东莞邦邻网站建设
  • 简述php网站开发流程网站 设计公司 温州
  • thinkphp8+layui多图上传,带删除\排序功能
  • LeetCode 合并K个升序链表
  • FFmpeg 基本API avformat_alloc_context 函数内部调用流程分析
  • ubuntu系统中ffmpeg+x264简易编译安装指南
  • FLAC to MP3 批量转换 Python
  • 开源鸿蒙6.1和8.1版本被确定为LTS建议版本,最新路标正式发布!-转自开源鸿蒙OpenHarmony社区
  • linux sdl图形编程之helloworld.
  • 开发一个网站系统报价电子商务网站建设试卷及答案
  • 瑞芯微算法环境搭建(2)------编译opencv
  • 计算机视觉(opencv)——人脸网格关键点检测
  • 自己做网站投入编程培训机构需要哪些证件
  • AXI总线的基础知识
  • 【泛微OA】泛微OA平台实现计算具体的天数
  • 「深度学习笔记1」深度学习全面解析:从基本概念到未来趋势
  • puppeteer 生成pdf,含动态目录,目录带页码
  • 深度学习的卷积神经网络中医舌诊断病系统-ResNet50与VGG16方法的比较研究
  • 如何查看网站空间wordpress图片多选
  • Android的Activity与intent知识点
  • 一、前置基础(MVC学习前提)_核心特性_【C# MVC 前置】委托与事件:从 “小区通知” 看懂 MVC 过滤器的底层逻辑
  • 网站建设年度汇报详情页设计理念怎么写
  • Spring Boot项目中Maven引入依赖常见报错问题解决
  • Android 13 启动的时候会显示一下logo,很不友好
  • seo网站快速排名外包关键词seo排名优化如何
  • Linux防火墙:核心机制与安全实践全解析