QtC++ 技术分析3 - IOStream

news2024/11/16 3:21:57

目录

    • iostream
      • scanf/printf
      • iostream 整体架构
        • 流相关类
        • 流缓冲区
      • 模板特化后整体结构
      • 文件流
        • 文件流对象创建
        • 常见文件流操作
        • 输出格式设定
        • 文件流状态
      • 字符串流
        • 字符串流内部缓冲区
        • 字符串流使用
      • 流缓冲区
      • 用户自定义 IO

iostream


scanf/printf

几种常见的输入输出流函数

  • scanf 从键盘接收输入数据
  • printf 向屏幕输出数据
  • fscanf 从文件输入数据
  • fprintf 向文件输出数据
  • sscanf 从内存块读取数据
  • sprintf 向内存块输出数据。

C 语言输入输出方法存在这些缺点:
无法在编译阶段检查 scanf/printf 函数组参数的错误;无法对 scanf/printf 函数组的接口进行扩展以处理新的数据类型;scanf/printf 函数组的执行速度慢;scanf/printf 函数组所占用的空间无法被优化。


iostream 整体架构

iostream 包括以下三个层次
在这里插入图片描述

输入输出特性

  • 无论是输出还是输入操作,都经由一个缓冲区进行处理
  • 输出时,数据先写入到缓冲区,直到缓冲区满,其中的数据才会被真正写入到外部设备
  • 即便仅输入一个字符,也必须经过缓冲区

流相关类

iostream 整体架构图
在这里插入图片描述

charT 表示流中字符的类型
模板参数 traits 表示字符的特征
模板参数 allocator 表示堆管理器,该参数的默认值是系统的堆管理器


类模板 basic_ios 负责管理流缓冲区。它含有一个指针,指向流缓冲区。它还含有一个状态信息,来记录流缓冲区中数据的完备性。

类模板 basic_istream 以及 basic_ostream 分别负责数据的输入和输出
basic_iostream 通过继承这两个类模板,既能处理输入也能处理输出。

类模板 basic_istringstream 从一个类型为 basic_string 的字符串对象读取数据
类模板 basic_ostringstream 则向这种类型的字符串对象输出数据


流缓冲区

basic_ios 派生类中的缓冲区指针会指向 basic_streambuf 或者 basic_filebuf 的对象

抽象类型 basic_streambuf 不含有任何关于外部设备的信息

类模板 basic_filebuf 将输出缓冲区中的数据写入文件,或者将文件中的数据读取到输入缓冲区


模板特化后整体结构

iostream 将所有的 charT 特化为 char ,所有的 traits 特化为 char_traits< char>

iostream 还将所有的 charT 特化为 wchar_t,所有的 traits 特化为char_traits<wchar_t >


文件流

basic_ifstream 以及 basic_ofstream 分别负责文件的输入和输出
basic_fstream 能够对文件进行输入和输出双向的操作


文件流对象创建

fstream 代码实例:创建一个文件流对象 fs,在文件“test.txt”的尾部写入数据

ios_base 中定义了 6 个常量

  • in 表示读一个文件
  • out 表示写一个文件
  • app 表示仅在一个文件的末尾写入
  • trunc 表示清空文件内容
  • binary 表示以二进制方式访问一个文件
  • ate(是 at end 的缩写)表示初始的读/写位置为文件的末尾。
fstream fs("test.txt", ios_base::out | ios_base::app)

当读入文件(in 模式)则要求文件必须存在;
当写入文件(out 模式)指定文件可不存在,由系统新建一个;


常见文件流操作

一般的,你可以直接使用 << 或者 >> 执行输入输出操作
下面代码展示使用 fstream 对文件读写流程

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

int main()
{
    // 打开文件,以输入、输出和追加的方式打开
    fstream fs("data\\test.txt", ios_base::in | ios_base::out | ios_base::app);

    // 检查文件是否成功打开,如果没有成功打开则输出错误信息并退出程序
    if (!fs) {
        cerr << "cannot open test.txt";
        exit(-1);
    }

    // 向文件中写入字符串 "hello, world\n"
    fs << "hello, world\n";

    // 将文件读写位置重新定位到文件开头
    fs.seekg(0);

    // 定义字符串变量 s,从文件中读取一个单词并存储到字符串 s 中
    string s;
    fs >> s;

    // 输出字符串 s
    cout << s;
}

常用 basic_istream 中的 getline()获取一整行的文本内容


输出格式设定

hex、oct、dec 分别将输出的数制设置为十六进制、八进制和默认的十进制
cout << hex << 20;

setw,流操作符,设置其后紧接着的那个数据的输出宽度
cout << swtw(4) << 3;

setprecision(m) 将设置小数点及其后面的数字占用 m 个字符的位置

boolalpha 流操作符,可以让 bool 类型数据输出形式为 true 何 false 而不是 1 和 0

left 流操作符,结果左对齐


文件流状态

C++流提供了以下的几个成员函数来返回一个流的状态信息

  1. eof()。如果输入流已经到达末尾,该函数返回真。
  2. bad()。如果用户试图对一个流对象执行非法操作,比如将文件指针移动到文件尾部之后的某个地方,该函数返回真,表示流对象被破坏了。
  3. fail()。如果施加到流的某个操作未能成功,比如一个输入流对象希望读取一个整数但是实际的输入数据却是一个字符串,该函数将返回真。
  4. good()。当以上条件都没有出现时,该函数返回真。

流使用者可以主动地分析流中的数据,调用成员函数 setstate()来设置流的状态信息

char ch;
if ((ch = ifs.get()) != '<' )
    is.setstate( ios_base::failbit );

字符串流

介绍类模板 basic_stringstream 读取和输出到一个 basic_string 对象的流程


字符串流内部缓冲区

stringstream 对象的流缓冲区指针指向一个 stringbuff 对象,该对象管理一个内部的字符缓冲区

内部字符缓冲区有两个指针:读取操作会后移“读指针”,而写入操作会后移“写指针”


字符串流使用

// istringstream使用
int i;
if (istringstream(argv[1]) >> i)

// ostringstream使用
struct date {
    int day,month,year;
} today = {9,3,2011};
ostringstream ostr;      ①
ostr << today.month << '-' << today.day <<'-' << today.year;if (ostr)
    cout<<ostr.str();

流缓冲区

可以令多个流对象共享一个流缓冲区

#include <iostream>
#include <fstream>
using namespace std;
int main()
{
    ofstream dec_stream( "demo.txt" );   ①
    ostream  hex_stream( dec_stream.rdbuf() );  ②
    hex_stream << hex << showbase;
    int a[4] = {12, 34, 56, 78};
    for (int i=1; i<4; i++){
            dec_stream << a[i];                        ③
            hex_stream << "[" << a[i] << "] ";}
    return 0;
}

流缓冲区可以执行复制操作

#include <fstream>
#include <sstream>
#include <iostream>
using namespace std;

int main()
{
    // 打开红楼梦文本文件
    ifstream fs("hong_lou_meng.txt");

    // 将文件内容读取到stringstream对象中
    stringstream ss;
    ss << fs.rdbuf();   // ①

    // 将stringstream对象中的内容转为字符串类型
    string str = ss.str();      // ②

    // 查找字符串 "黛玉" 最后一次出现的位置
    string::size_type pos = str.rfind("黛玉");

    // 将stringstream对象的读写位置定位到 "黛玉" 最后一次出现的位置
    ss.seekg(pos);

    // 读取一行字符串,即 "黛玉" 最后一次出现的那句话
    string one_line;
    getline(ss, one_line);

    // 输出 "黛玉" 最后一次出现的那句话
    cout << one_line << endl;

    return 0;
}

用户自定义 IO

通过定义类,附加两个友元函数,并利用 ostreaminstream ,即可实现自定义 IO

#include <iostream> //包含输入输出流库
using namespace std; //使用标准命名空间

class CPoint { //定义CPoint类
public:
    CPoint(double p_x=0, double p_y=0) {x=p_x;  y=p_y;}; //构造函数
    friend ostream& operator << (ostream&, const CPoint&); //输出运算符重载函数的友元声明
    friend istream& operator >> (istream&, CPoint&); //输入运算符重载函数的友元声明
private:
    double x,y; //CPoint对象的x和y坐标
};

ostream& operator <<( ostream& os, const CPoint& point ) //输出运算符重载函数的实现
{
    os << "<" << point.x << "," << point.y << ">"; //输出CPoint对象的坐标
    return os; //返回输出流对象
}

istream& operator >>(istream& is, CPoint& point) //输入运算符重载函数的实现
{
    char ch;
    is >> ch;
    if ( ch!='<'){  //如果输入不是以 '<' 开始,则输入失败
            is.setstate( ios_base::failbit ); //设置输入流的状态为失败
            return is; //返回输入流对象
    }
    is >> point.x >> ch >> point.y >> ch; //输入CPoint对象的坐标
}

int main() //主函数
{
    CPoint p; //定义一个CPoint对象p
    while ( cin>> p ) //从标准输入流中读取CPoint对象,如果读取成功则进入循环
            cout << p << endl; //输出CPoint对象p,然后换行
}

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

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

相关文章

哆啦A梦(Python代码实现)

目录 1 送她的多啦A梦 2 白驹过隙 3 Python代码实现 1 送她的多啦A梦 一个哆啦A梦让她开心开心好久好久。我也很开心&#xff0c;昨天送了一个实体模型&#xff0c;今天用Python代码再弄一个送给她。 哆啦A梦&#xff08;日语&#xff1a;ドラえもん&#xff0c;英语&…

linux页框回收之shrink_node函数源码剖析

概述 《Linux内存回收入口_nginux的博客-CSDN博客》前文我们概略的描述了几种内存回收入口&#xff0c;我们知道几种回收入口最终都会调用进入shrink_node函数&#xff0c;本文将以Linux 5.9源码来描述shrink_node函数的源码实现。 函数调用流程图 scan_control数据结构 str…

如何关闭谷歌浏览器自动更新

适用范围: 写自动化脚本时&#xff0c;需要安装浏览器驱动&#xff0c;安装浏览器驱动时需要下载对应的浏览器驱动版本&#xff0c;如果浏览器版本一直在自动更新的话&#xff0c;自动化脚本会报错浏览器版本和浏览器驱动不匹配&#xff0c;所以建议关闭谷歌浏览器自动更新&am…

认识 springboot 之 它的配置文件 -2

前言 本篇了解springboot中配置的作用&#xff0c;介绍配置文件的种类&#xff0c;介绍简单使用配置文件&#xff0c;简单的小技巧如何设置注释&#xff0c;开启热部署等等&#xff0c;如有错误&#xff0c;请在评论区指正&#xff0c;让我们一起交流&#xff0c;共同进步&…

内存分区模型

C程序在执行时&#xff0c;将内存大方向划分为4个区域 代码区&#xff1a;存放函数体的二进制代码&#xff0c;由操作系统进行管理的全局区&#xff1a;存放全局变量和静态变量以及常量栈区&#xff1a;由编译器自动分配释放, 存放函数的参数值,局部变量等堆区&#xff1a;由程…

ReentrantLock锁的实现

ReentrantLock基于AQS&#xff0c;在并发编程中可以实现公平锁和非公平锁来对同步资源进行控制&#xff0c;并且是可重入锁。 1.ReentrantLock中的类的继承结构&#xff1a; 2.构造方法&#xff1a; 3.非公平锁的实现 看是否能够通过CAS来设置state来获取到锁&#xff0c;如果…

【数据结构】这堆是什么

目录 1.二叉树的顺序结构 2.堆的概念及结构 3.堆的实现 3.1 向上调整算法与向下调整算法 3.2 堆的创建 3.3 建堆的空间复杂度 3.4 堆的插入 3.5 堆的删除 3.6 堆的代码的实现 4.堆的应用 4.1 堆排序 4.2 TOP-K问题 首先&#xff0c;堆是一种数据结构&#xff0c;一种特…

Selenium开发环境搭建

1.下载Python https://www.python.org/downloads/ 下载下来选择自己创建的路径进行安装&#xff0c;然后配置环境变量 cmd命令框查看 2.安装selenium cmd命令框输入&#xff1a; pip install selenium3.下载pycharm https://www.jetbrains.com/pycharm/download/#sec…

VLOOKUP多条件查询

LOOKUP(1,0/((A3:A15A18)*(C3:C15C18)),F3:F15)

打印Winfrom控件实现简陋版的打印(C#)

本文在前面写的博文基础上进行修改&#xff1a;利用Graphics的CopyFromScreen实现简陋版的打印(C#)_zxy2847225301的博客-CSDN博客 通过截图的方式进行打印在前面的文章后面已经介绍过&#xff0c;有问题。 UI布局如下&#xff1a; 代码如下&#xff1a; using System; using…

无涯教程-jQuery - Dialog组件函数

小部件对话框函数可与JqueryUI中的小部件一起使用。对话框是在HTML页面上显示信息的一种不错的方法。对话框是一个带有标题和内容区域的浮动窗口。此窗口可以移动&#xff0c;调整大小&#xff0c;并且默认情况下可以使用" X"图标关闭。 Dialog - 语法 $( "#d…

CAN转ETHERCAT网关can协议和485协议区别

大家好&#xff0c;今天要跟大家分享一款自主研发的通讯网关&#xff0c;JM-ECT-CAN。这款产品能够将各种CAN总线和ETHERCAT网络连接起来&#xff0c;实现高效的数据传输和通信。那么&#xff0c;这款通讯网关具体有哪些功能和特点呢&#xff1f;接下来&#xff0c;我们就一起来…

苍穹外卖心得与总结【对比瑞吉】【如何获得铁粉】

对于苍穹外卖项目&#xff0c;从学习课程加复习已经13天了。 对于一名已经学习过SSMLinuxRedis数据库的Java练习生来说&#xff0c;这个项目相对于之前学习的《瑞吉外卖》新增了很多功能和技术&#xff0c;是很值得练手和提升的课程&#xff0c;下面给出自己的一些见解。&#…

大厂程序员的水平比非大厂高很多嘛?

最近一个月&#xff0c;筛选了一百多份简历&#xff0c;前前后后面试了二三十人&#xff0c;基本上都是有大厂经历的人。同时&#xff0c;也录用了几个有大厂经历的。但整体而言&#xff0c;打破了对大厂出来的都是优质人才的幻觉。看到的实际情况与想象中的落差还是比较大的。…

从零开始学python(十二)如何成为一名优秀的爬虫工程师

前言 回顾之前讲述了python语法编程 必修入门基础和网络编程&#xff0c;多线程/多进程/协程等方面的内容&#xff0c;后续讲到了数据库编程篇MySQL&#xff0c;Redis&#xff0c;MongoDB篇&#xff0c;和机器学习&#xff0c;全栈开发&#xff0c;数据分析前面没看的也不用往…

ChatIE:通过多轮问答问题实现实命名实体识别和关系事件的零样本信息抽取,并在NYT11-HRL等数据集上超过了全监督模型

项目设计集合&#xff08;人工智能方向&#xff09;&#xff1a;助力新人快速实战掌握技能、自主完成项目设计升级&#xff0c;提升自身的硬实力&#xff08;不仅限NLP、知识图谱、计算机视觉等领域&#xff09;&#xff1a;汇总有意义的项目设计集合&#xff0c;助力新人快速实…

【机器学习】Cost Function

Cost Function 1、计算 cost2、cost 函数的直观理解3、cost 可视化总结附录 首先&#xff0c;导入所需的库&#xff1a; import numpy as np %matplotlib widget import matplotlib.pyplot as plt from lab_utils_uni import plt_intuition, plt_stationary, plt_update_onclic…

【数字IC设计】VCS仿真DesignWare IP

DesignWare介绍 DesignWare是SoC/ASIC设计者最钟爱的设计IP库和验证IP库。它包括一个独立于工艺的、经验证的、可综合的虚拟微架构的元件集合&#xff0c;包括逻辑、算术、存储和专用元件系列&#xff0c;超过140个模块。DesignWare和 Design Compiler的结合可以极大地改进综合…

c++ 给无名形参提供默认值

如上图&#xff0c;若函数的形参不在函数体里使用&#xff0c;可以不提供形参名&#xff0c;而且可以给此形参提供默认值。也能编译通过。 在看vs2019上的源码时&#xff0c;也出现了这种写法。应用SFINAE&#xff08;substitute false is not an error&#xff09;原则&#x…

Go Ethereum源码学习笔记 001 Geth Start

Go Ethereum源码学习笔记 前言[Chapter_001] 万物的起点: Geth Start什么是 geth&#xff1f;go-ethereum Codebase 结构 Geth Start前奏: Geth Consolegeth 节点是如何启动的NodeNode的关闭 Ethereum Backend附录 前言 首先读者需要具备Go语言基础&#xff0c;至少要通关菜鸟…