(P58)io流类库:什么是I/O,什么是流,流类库继承体系,标准输入/输出流

2024-06-08 05:58

本文主要是介绍(P58)io流类库:什么是I/O,什么是流,流类库继承体系,标准输入/输出流,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 1.什么是I/O
    • 2.什么是流
    • 3.流类库继承体系
    • 4.标准输入/输出流

1.什么是I/O

  • 数据的输入和输出(INPUT/OUTPUT简写为I/O)
  • 3种类型的IO
    (1)标准输入输出流
    对标准输入设备和标准输出设备的输入输出简称为标准I/O
    (2)文件流
    对在外存磁盘上文件的输入输出简称为文件I/O
    (3)字符串流
    对内存中指定的字符串存储空间的输入输出简称为串I/O

2.什么是流

  • 数据输出输出的过程,可以形象地看成流
  • 从流中获取数据的操作称为“提取”(输入,>>)操作
  • 从流中添加数据的操作称为“插入”(输出,<<)操作
cin>>n		从标准输入获取变量n。从输入流到变量,称之为输入
cout<<n		向标准输出插入数据变量n。从变量到输出流,称之为输出
>>,<<箭头指向的方向代表了数据流动的方向
  • 标准IO,就有标准输入输出流
  • 文件IO,就有文件流
  • 字符串IO,就有字符串流

3.流类库继承体系

  • ios类和streambuf是平行类,大部分流类都直接或间接继承至这俩类
    ios是与输入输出相关的类;streambuf是与缓冲区相关的类

  • ios_base是ios基类,给ios类提供了流状态,输入输出格式化的功能

  • istream类继承至ios,提供流的输入操作,是输入流,重载了>>

  • ostream输出流,重载了输出的操作,重载<<

  • iostream输入输出都有

  • 字符串输入流:istringstream(>>输入操作),字符串输出流ostringstrea(<<输出操作),字符串输入输出流stringstream(>>,<<操作),
    字符串的三个流与stringbuf是组合关系,也就是这三流类包含了stringbuf成员
    在这里插入图片描述

  • 流库具有2个平行的基类:streambuf和ios类,所有流类均以两者之一作为基类

  • streambuf类提供对缓冲区的低级操作:设置缓冲区、对缓冲区指针操作、向缓冲区存/取字符

  • ios_base,ios类记录流状态,支持对streambuf的缓冲区输入/输出的格式化或非格式化转换

  • strstreambuf:使用串保存字符序列。扩展streambuf在缓冲区提取和插入的管理
    字符串流缓冲区

  • 使用文件保存字符序列。包括打开文件:读/写、查找字符
    文件流缓冲区

  • 查看类定义
    在这里插入图片描述
    cin是istream类的一个对象,cout是ostream类的一个对象
    在这里插入图片描述
    在这里插入图片描述
    istream是basic_istream模板的一个特化,实际上真正的类应该是basic_istream<char, char_traits>;
    ostream是basic_ostream模板的一个特化
    在这里插入图片描述
    在这里插入图片描述
    basic_istream继承至basic_ios,并不是继承至ios
    在这里插入图片描述
    在这里插入图片描述
    实际上ios是basic_ios模板的一个特化
    在这里插入图片描述
    在这里插入图片描述
    清除流流状态
    在这里插入图片描述
    设置流状态
    在这里插入图片描述
    格式化操作
    在这里插入图片描述
    很多格式化操作可能由ios_base提供
    在这里插入图片描述
    格式化操作,科学计数法,输出宽度
    在这里插入图片描述

  • ostream
    在这里插入图片描述
    在这里插入图片描述
    插入运算符,布尔类型的输出操作
    在这里插入图片描述
    short类型的输出操作
    在这里插入图片描述
    其他,以此类推
    在这里插入图片描述
    在这里插入图片描述

  • eg:P58\01.cpp

#include <iostream>using namespace std;//实际上是2个类对象
// cout;
// cin;int main(void)
{int n;cout << n <<endl;//在ostream类中重载了<<运算符,以成员函数方式重载MyString str;cout<<str;//不能以成员函数的方式重载的原因是:不能去更改ostream类的代码,如果每增加一个类,就去更改类重载//的代码,这样不好。//所以要输出自定义的类,要重载<<插入运算符,要用友元的方式重载return 0;
}
  • 为什么将ostream和istream看成是继承ios?
    在这里插入图片描述
    将basic_ios<_Elem, _Traits>用ios替换,把basic_istream用iostream替换。所以istream类继承至ios类。ostream类似
    在这里插入图片描述

  • eg2:【C++】关于std::ostream的构造函数

error


#include <iostream>
#include <sstream>
#include <string>using namespace std;int main(int argc, char* argv[]) 
{ostream os;stringstream ss1(argv[1]);os << "ss1:" << ss1.str() << endl;ss1 >>  hex >> supi;os << "supi:" << supi << endl;cout << endl;getchar();return 0;
}

但出现错误如下:

错误:'std :: basic_ostream&lt; _CharT,_Traits&gt; :: basic_ostream()[with _CharT = char;

错误原因
查看了下std::ostream的构造函数,如下:

public:
//explicit用来防止由构造函数定义的隐式转换
explicitbasic_ostream(__streambuf_type* __sb){ this->init(__sb); }protected:basic_ostream(){ this->init(0); }#if __cplusplus >= 201103L// Non-standard constructor that does not call init()basic_ostream(basic_iostream<_CharT, _Traits>&) { }basic_ostream(const basic_ostream&) = delete;basic_ostream(basic_ostream&& __rhs): __ios_type(){ __ios_type::move(__rhs); }// 27.7.3.3 Assign/swapbasic_ostream& operator=(const basic_ostream&) = delete;basic_ostream&operator=(basic_ostream&& __rhs){swap(__rhs);return *this;
}

可以看到ostream类的默认构造函数是保护类型,而带参数的构造函数则是公有的,根据public和protected的功能,我们要定义一个ostream对象,必须要在参数中传入streambuf类型的指针才可以,否则会报编译错误。

success:


#include <iostream>
#include <fstream>using namespace std;int main()
{filebuf buf;if ( buf.open("/proc/self/fd/1", ios::out) == nullptr ){cerr << "stdout open failed" << endl;return -1;}ostream out(&buf);return 0;
}

总结:std::ostream,std::istream或std::iostream是std::stringstream,std::fstream等类的基类。

  • 这些类构造函数是保护类型,是不允许拷贝或者赋值的,所以它也不能直接作为返回类型和参数传递,很多时候需要使用引用来进行传递。
  • 所以只能实例化其派生类,然后使用引用或者指针来指向实例实现调用。(streambuf也一样,所以上面使用了其子类filebuf)

success:

  • 这里提供了一种便捷方法,将std::cout控制台输出流实例赋给std::ostream就可以了。

#include <iostream>
#include <sstream>
#include <string>using namespace std;int main(int argc, char* argv[]) 
{ostream &os = std::cout;stringstream ss1(argv[1]);os << "ss1:" << ss1.str() << endl;ss1 >>  hex >> supi;os << "supi:" << supi << endl;cout << endl;getchar();return 0;
}

4.标准输入/输出流

  • C++为用户进行标准I/O操作定义了四个类对象:cin,cout,cerr和clog
    (1)cin为istream流类的对象,代表输入设备键盘,后3个为ostream流类的对象
    (2)out代表标准输出设备显示器
    (3)cerr(错误输出)和clog(位置输出)含义相同,均代表错误信息输出设备显示器

  • ostream流的操作
    (1)operator <<,插入运算符的重载
    (2)put(),输出
    (3)write(),输出

  • eg:P58\02.cpp

#include <iostream>using namespace std;int main(void)
{int n = 100;int n2 = 200;cout <<n<<" "<<n2<<endl;return 0;
}
  • 测试:
    为什么可以连续使用<<操作?注意:<<的返回值,<<操作返回一个ostream对象的引用,以及<<操作的重载功能(默认情况下重载了一些基本类型)
    运算符重载返回的是对象的引用,运算符重载本质上是函数重载,cout <<n函数的返回值对象的引用(cout就是ostream类型),也还是cout对象,cout对象还可以继续输出
    在这里插入图片描述
    打断点,F9跟踪进去
    在这里插入图片描述
    输入F11,返回的是对象的引用
    在这里插入图片描述
    basic_ostream<_Elem, _Traits>实际上就是ostream类型
    在这里插入图片描述
  • eg:P58\03.cpp
#include <iostream>using namespace std;int main(void)
{int n = 100;int n2 = 200;cout <<n<<" "<<n2<<endl;//put是ostream类的一个成员函数//put方法的返回值也是ostream对象的引用,所以也可以连续使用cout.put('H');cout.put('i');cout.put(' ');cout.put('H').put('i').put('\n');return 0;
}
  • 测试:
    put()操作
    输出单个字符
    返回一个ostream对象的引用
    cout.put(‘H’).put(‘i’);
    put方法的返回值也是ostream对象的引用,所以也可以连续使用
    在这里插入图片描述
    在这里插入图片描述
  • eg:P58\04.cpp
#include <iostream>using namespace std;int main(void)
{int n = 100;int n2 = 200;cout <<n<<" "<<n2<<endl;//put是ostream类的一个成员函数//put方法的返回值也是ostream对象的引用,所以也可以连续使用cout.put('H');cout.put('i');cout.put(' ');cout.put('H').put('i').put('\n');char buf[] = "test!!!!!";cout.write(buf, 5);return 0;
}
  • 测试:
    write操作
    write(buf, len)
    write()返回一个ostream对象的引用
    cout.write(buf, len)//char buf[len],输出一个缓冲区,并指定缓冲区的长度
    在这里插入图片描述

  • istream流的操作
    (1)operator>>操作,重载了提取运算符>>
    (2)get()
    (3)getline()
    (4)read()
    (5)peek()
    (6)peek()
    (7)putback()

  • eg:P58\05.cpp

#include <iostream>using namespace std;int main(void)
{int n;char ch;cin>>n>>ch;cout<<"n="<<n<<" "<<"ch="<<ch<<endl;return 0;
}
  • 测试:
    为什么可以连续使用>>操作?注意:>>的返回值,>>操作返回一个istream对象的引用,>>操作的重载功能

在这里插入图片描述

  • eg:P58\06.cpp
#include <iostream>using namespace std;int main(void)
{// int n;// char ch;// cin>>n>>ch;// cout<<"n="<<n<<" "<<"ch="<<ch<<endl;int ch = cin.get();cout<<ch<<endl;char ch;cin.get(ch);cout<<ch<<endl;char ch1;char ch2;cin.get(ch1).get(ch2);cout<<ch1<<" "<<ch2<<endl;return 0;
}
  • 测试
    get操作
    (1)读取单个字符
    (2)返回一个整数(输入的是字符,返回的是字符的ASCII码)
    (3)get对回车换行的处理
    get(char&)操作
    (1)读取单个字符
    (2)返回一个istream对象引用
    输出A的ASCII码值为65
    在这里插入图片描述
    获取一个字符A
    在这里插入图片描述
    get返回的是对象的引用,所以可以使用多次get
    在这里插入图片描述
  • eg:P58\07.cpp
#include <iostream>using namespace std;int main(void)
{// int n;// char ch;// cin>>n>>ch;// cout<<"n="<<n<<" "<<"ch="<<ch<<endl;// int ch = cin.get();// cout<<ch<<endl;// char ch;// cin.get(ch);// cout<<ch<<endl;// char ch1;// char ch2;// cin.get(ch1).get(ch2);// cout<<ch1<<" "<<ch2<<endl;//getline按行获取,即使遇到空白字符,也会提取到buf中//最多获取9个字符,还有1个是换行符//getline不接收换行符char buf[10] = {0};cin.getline(buf, 10);cout<<buf<<endl;//提取运算符>>遇到空白字符就停止char buf[10] = {0};cin>>buf;cout<<buf<<endl;return 0;
}
  • 测试:
    getline操作,按行获取
    (1)读取一行,读取回车键
    (2)返回istream对象的引用
    (3)getline()操作与>>的区别:
    char string1[256];
    cin.getline(string1, 256);//get a whole line
    cin>>string1;//stop at the 1st blank space
    在这里插入图片描述
    在这里插入图片描述

  • eg:P58\08.cpp

#include <iostream>using namespace std;int main(void)
{// int n;// char ch;// cin>>n>>ch;// cout<<"n="<<n<<" "<<"ch="<<ch<<endl;// int ch = cin.get();// cout<<ch<<endl;// char ch;// cin.get(ch);// cout<<ch<<endl;// char ch1;// char ch2;// cin.get(ch1).get(ch2);// cout<<ch1<<" "<<ch2<<endl;//getline按行获取,即使遇到空白字符,也会提取到buf中//最多获取9个字符,还有1个是换行符//getline不接收换行符// char buf[10] = {0};// cin.getline(buf, 10);// cout<<buf<<endl;// //提取运算符>>遇到空白字符就停止// char buf[10] = {0};// cin>>buf;// cout<<buf<<endl;//read对空白字符照读不误char buf[10] = {0};cin.read(buf, 5);cout<<buf<<endl;return 0;
}
  • 测试
    read(buf, len)
    返回一个istream对象的引用
    对空白字符照读不误

在这里插入图片描述
换行也会读取,a换行bcd
在这里插入图片描述

  • eg:P58\09.cpp
#include <iostream>using namespace std;int main(void)
{char c[10], c2, c3;c2 = cin.get();c3 = cin.get();cin.putback(c2);//该例子来自vs,按下F11cin.getline(&c[0], 9);cout << c <<endl;return 0}
  • 测试
    peek与putback
    peek:查看而不读取
    putback:将一个字符添加到流
    输入流中有abcdefg
    将a获取到c2变量,将b获取到c3变量,此时流中只有cdefg,然后再把c2进行putback放回流中
    在这里插入图片描述

这篇关于(P58)io流类库:什么是I/O,什么是流,流类库继承体系,标准输入/输出流的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1041372

相关文章

使用TomCat,service输出台出现乱码的解决

《使用TomCat,service输出台出现乱码的解决》本文介绍了解决Tomcat服务输出台中文乱码问题的两种方法,第一种方法是修改`logging.properties`文件中的`prefix`和`... 目录使用TomCat,service输出台出现乱码问题1解决方案问题2解决方案总结使用TomCat,

C++中实现调试日志输出

《C++中实现调试日志输出》在C++编程中,调试日志对于定位问题和优化代码至关重要,本文将介绍几种常用的调试日志输出方法,并教你如何在日志中添加时间戳,希望对大家有所帮助... 目录1. 使用 #ifdef _DEBUG 宏2. 加入时间戳:精确到毫秒3.Windows 和 MFC 中的调试日志方法MFC

Python使用Colorama库美化终端输出的操作示例

《Python使用Colorama库美化终端输出的操作示例》在开发命令行工具或调试程序时,我们可能会希望通过颜色来区分重要信息,比如警告、错误、提示等,而Colorama是一个简单易用的Python库... 目录python Colorama 库详解:终端输出美化的神器1. Colorama 是什么?2.

Python 标准库time时间的访问和转换问题小结

《Python标准库time时间的访问和转换问题小结》time模块为Python提供了处理时间和日期的多种功能,适用于多种与时间相关的场景,包括获取当前时间、格式化时间、暂停程序执行、计算程序运行时... 目录模块介绍使用场景主要类主要函数 - time()- sleep()- localtime()- g

【测试】输入正确用户名和密码,点击登录没有响应的可能性原因

目录 一、前端问题 1. 界面交互问题 2. 输入数据校验问题 二、网络问题 1. 网络连接中断 2. 代理设置问题 三、后端问题 1. 服务器故障 2. 数据库问题 3. 权限问题: 四、其他问题 1. 缓存问题 2. 第三方服务问题 3. 配置问题 一、前端问题 1. 界面交互问题 登录按钮的点击事件未正确绑定,导致点击后无法触发登录操作。 页面可能存在

顺序表之创建,判满,插入,输出

文章目录 🍊自我介绍🍊创建一个空的顺序表,为结构体在堆区分配空间🍊插入数据🍊输出数据🍊判断顺序表是否满了,满了返回值1,否则返回0🍊main函数 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以:点赞+关注+评论+收藏(一键四连)哦~ 🍊自我介绍   Hello,大家好,我是小珑也要变强(也是小珑),我是易编程·终身成长社群的一名“创始团队·嘉宾”

数据治理框架-ISO数据治理标准

引言 "数据治理"并不是一个新的概念,国内外有很多组织专注于数据治理理论和实践的研究。目前国际上,主要的数据治理框架有ISO数据治理标准、GDI数据治理框架、DAMA数据治理管理框架等。 ISO数据治理标准 改标准阐述了数据治理的标准、基本原则和数据治理模型,是一套完整的数据治理方法论。 ISO/IEC 38505标准的数据治理方法论的核心内容如下: 数据治理的目标:促进组织高效、合理地

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出 在数字化时代,文本到语音(Text-to-Speech, TTS)技术已成为人机交互的关键桥梁,无论是为视障人士提供辅助阅读,还是为智能助手注入声音的灵魂,TTS 技术都扮演着至关重要的角色。从最初的拼接式方法到参数化技术,再到现今的深度学习解决方案,TTS 技术经历了一段长足的进步。这篇文章将带您穿越时

C 标准库 - `<float.h>`

C 标准库 - <float.h> 概述 <float.h> 是 C 标准库中的一个头文件,它定义了与浮点数类型相关的宏。这些宏提供了关于浮点数的属性信息,如精度、最小和最大值、以及舍入误差等。这个头文件对于需要精确控制浮点数行为的程序非常有用,尤其是在数值计算和科学计算领域。 主要宏 <float.h> 中定义了许多宏,下面列举了一些主要的宏: FLT_RADIX:定义了浮点数的基数。

JavaSE——封装、继承和多态

1. 封装 1.1 概念      面向对象程序三大特性:封装、继承、多态 。而类和对象阶段,主要研究的就是封装特性。何为封装呢?简单来说就是套壳屏蔽细节 。     比如:对于电脑这样一个复杂的设备,提供给用户的就只是:开关机、通过键盘输入,显示器, USB 插孔等,让用户来和计算机进行交互,完成日常事务。但实际上:电脑真正工作的却是CPU 、显卡、内存等一些硬件元件。