[转]20110324-C++的iostream标准库介绍(1)

2024-03-06 20:32

本文主要是介绍[转]20110324-C++的iostream标准库介绍(1),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

出处:PConline 2005年04月05日 作者:管宁 责任编辑:xietaoming


      我们从一开始就一直在利用C++的输入输出在做着各种练习,输入输出是由iostream库提供的,所以讨论此标准库是有必要的,它与C语言的stdio库不同,它从一开始就是用多重继承与虚拟继承实现的面向对象的层次结构,作为一个c++的标准库组件提供给程序员使用。

iostream为内置类型类型对象提供了输入输出支持,同时也支持文件的输入输出,类的设计者可以通过对iostream库的扩展,来支持自定义类型的输入输出操作。

为什么说要扩展才能提供支持呢?我们来一个示例。

#include  
#include  
using namespace std;     
class Test 

public: 
        Test(int a=0,int b=0) 
        { 
            Test::a=a; 
            Test::b=b; 
        } 
int a; 
int b; 
}; 
int main() 

    Test t(100,50); 
    printf("%???",t);//不明确的输出格式 
    scanf("%???",t);//不明确的输入格式 
cout<cin>>t;//同样不够明确 
    system("pause"); 
}

由于自定义类的特殊性,在上面的代码中,无论你使用c风格的输入输出,或者是c++的输入输出都不是不明确的一个表示,由于c语言没有运算符重载机制,导致stdio库的不可扩充性,让我们无法让printf()和scanf()支持对自定义类对象的扩充识别,而c++是可以通过运算符重载机制扩充iostream库的,使系统能能够识别自定义类型,从而让输入输出明确的知道他们该干什么,格式是什么。
在上例中我们之所以用printf与cout进行对比目的是为了告诉大家,C与C++处理输入输出的根本不同,我们从c远的输入输出可以很明显看出是函数调用方式,而c++的则是对象模式,cout和cin是ostream类和istream类的对象
C++中的iostream库主要包含下图所示的几个头文件:

我们所熟悉的输入输出操作分别是由istream(输入流)和ostream(输出流)这两个类提供的,为了允许双向的输入/输出,由istream和ostream派生出了iostream类。
类的继承关系见下图:

iostream库定义了以下三个标准流对象:
1.cin,表示标准输入(standard input)的istream类对象。cin使我们可以从设备读如数据。
2.cout,表示标准输出(standard output)的ostream类对象。cout使我们可以向设备输出或者写数据。
3.cerr,表示标准错误(standard error)的osttream类对象。cerr是导出程序错误消息的地方,它只能允许向屏幕设备写数据。
输出主要由重载的左移操作符(<<)来完成,输入主要由重载的右移操作符(>>)完成。
>>a表示将数据放入a对象中。
<这些标准的流对象都有默认的所对应的设备,见下表:

图中的意思表明cin对象的默认输入设备是键盘,cout对象的默认输出设备是显示器屏幕。
那么原理上C++有是如何利用cin/cout对象与左移和右移运算符重载来实现输入输出的呢?
下面我们以输出为例,说明其实现原理
cout是ostream类的对象,因为它所指向的是标准设备(显示器屏幕),所以它在iostream头文件中作为全局对象进行定义。
ostream cout(stdout);//其默认指向的C中的标准设备名,作为其构造函数的参数使用。
在iostream.h头文件中,ostream类对应每个基本数据类型都有其友元函数对左移操作符进行了友元函数的重载。
ostream& operator<<(ostream &temp,int source);
ostream& operator<<(ostream &temp,char *ps);
。。。。等等
一句输出语句:cout<<"www.cndev-lab.com";,事实上调用的就是ostream& operator<<(ostream &temp,char *ps);这个运算符重载函数,由于返回的是流对象的引用,引用可以作为左值使用,所以当程序中有类似cout<<"www.cndev-lab.com"<<"中国软件开发实验室";这样的语句出现的时候,就能够构成连续输出。

由于iostream库不光支持对象的输入输出,同时也支持文件流的输入输出,所以在详细讲解左移与右移运算符重载只前,我们有必要先对文件的输入输出以及输入输出的控制符有所了解。
和文件有关系的输入输出类主要在fstream.h这个头文件中被定义,在这个头文件中主要被定义了三个类,由这三个类控制对文件的各种输入输出操作,他们分别是ifstream、ofstream、fstream,其中fstream类是由iostream类派生而来,他们之间的继承关系见下图所示。

由于文件设备并不像显示器屏幕与键盘那样是标准默认设备,所以它在fstream.h头文件中是没有像cout那样预先定义的全局对象,所以我们必须自己定义一个该类的对象,我们要以文件作为设备向文件输出信息(也就是向文件写数据),那么就应该使用ofstream类。
ofstream类的默认构造函数原形为:
ofstream::ofstream(const char *filename,int mode = ios::out,int openprot = filebuf::openprot);
filename: 要打开的文件名
mode: 要打开文件的方式
prot: 打开文件的属性
其中mode和openprot这两个参数的可选项表见下表:
mode属性表
ios::app: 以追加的方式打开文件
ios::ate: 文件打开后定位到文件尾,ios:app就包含有此属性
ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文
ios::in: 文件以输入方式打开
ios::out: 文件以输出方式打开
ios::trunc: 如果文件存在,把文件长度设为0
可以用“或”把以上属性连接起来,如ios::out|ios::binary。
openprot属性表:
0:普通文件,打开访问
1:只读文件
2:隐含文件
4:系统文件
可以用“或”或者“+”把以上属性连接起来 ,如3或1|2就是以只读和隐含属性打开文件。

示例代码如下:

//程序作者:管宁 
//站点:www.cndev-lab.com 
//所有稿件均有版权,如要转载,请务必著名出处和作者 
#include  
using namespace std; 
int main()  

    ofstream myfile("c://1.txt",ios::out|ios::trunc,0); 
    myfile<<"中国软件开发实验室"<    myfile.close() 
    system("pause"); 
}

文件使用完后可以使用close成员函数关闭文件。
ios::app为追加模式,在使用追加模式的时候同时进行文件状态的判断是一个比较好的习惯。
示例如下:

//程序作者:管宁 
//站点:www.cndev-lab.com 
//所有稿件均有版权,如要转载,请务必著名出处和作者 
#include  
#include  
using namespace std; 
int main()  

    ofstream myfile("c://1.txt",ios::app,0); 
if(!myfile)//或者写成myfile.fail() 
    { 
cout<<"文件打开失败,目标文件状态可能为只读!"; 
        system("pause"); 
        exit(1); 
    } 
    myfile<<"中国软件开发实验室"<    myfile.close(); 
}

在定义ifstream和ofstream类对象的时候,我们也可以不指定文件。以后可以通过成员函数open()显式的把一个文件连接到一个类对象上。
例如:

//程序作者:管宁 
//站点:www.cndev-lab.com 
//所有稿件均有版权,如要转载,请务必著名出处和作者 
#include  
#include  
using namespace std; 
int main()  

    ofstream myfile; 
    myfile.open("c://1.txt",ios::out|ios::app,0); 
if(!myfile)//或者写成myfile.fail() 
    { 
cout<<"文件创建失败,磁盘不可写或者文件为只读!"; 
        system("pause"); 
        exit(1); 
    } 
    myfile<<"中国软件开发实验室"<    myfile.close(); 
}

下面我们来看一下是如何利用ifstream类对象,将文件中的数据读取出来,然后再输出到标准设备中的例子。
代码如下:

//程序作者:管宁 
//站点:www.cndev-lab.com 
//所有稿件均有版权,如要转载,请务必著名出处和作者 
#include  
#include  
#include  
using namespace std; 
int main()  

    ifstream myfile; 
    myfile.open("c://1.txt",ios::in,0); 
if(!myfile) 
    { 
cout<<"文件读错误"; 
        system("pause"); 
        exit(1); 
    } 
char ch; 
string content; 
while(myfile.get(ch)) 
    { 
        content+=ch; 
cout.put(ch);//cout<    } 
    myfile.close(); 
cout<    system("pause"); 
}

上例中,我们利用成员函数get(),逐一的读取文件中的有效字符,再利用put()成员函数,将文件中的数据通过循环逐一输出到标准设备(屏幕)上,get()成员函数会在文件读到默尾的时候返回假值,所以我们可以利用它的这个特性作为while循环的终止条件,我们同时也在上例中引入了C++风格的字符串类型string,在循环读取的时候逐一保存到content中,要使用string类型,必须包含string.h的头文件。

我们在简单介绍过ofstream类和ifstream类后,我们再来看一下fstream类,fstream类是由iostream派生而来,fstream类对象可以同对文件进行读写操作。

示例代码如下:

//程序作者:管宁 
//站点:www.cndev-lab.com 
//所有稿件均有版权,如要转载,请务必著名出处和作者 
#include  
#include  
using namespace std; 
int main()  

fstream myfile; 
    myfile.open("c://1.txt",ios::out|ios::app,0); 
if(!myfile) 
    { 
cout<<"文件写错误,文件属性可能为只读!"<        system("pause"); 
        exit(1); 
    } 
    myfile<<"中国软件开发实验室"<    myfile.close(); 
    myfile.open("c://1.txt",ios::in,0); 
if(!myfile) 
    { 
cout<<"文件读错误,文件可能丢失!"<        system("pause"); 
        exit(1); 
    } 
char ch; 
while(myfile.get(ch)) 
    { 
cout.put(ch); 
    } 
    myfile.close(); 
    system("pause"); 
}

由于fstream类可以对文件同时进行读写操作,所以对它的对象进行初始话的时候一定要显式的指定mode和openprot参数。

接下来我们来学习一下串流类的基础知识,什么叫串流类
简单的理解就是能够控制字符串类型对象进行输入输出的类,C++不光可以支持C++风格的字符串流控制,还可以支持C风格的字符串流控制。
我们先看看看C++是如何对C风格的字符串流进行控制的,C中的字符串其实也就是字符数组,字符数组内的数据在内存中的位置的排列是连续的,我们通常用char str[size]或者char *str的方式声明创建C风格字符数组,为了能让字符数组作为设备并提供输入输出操作,C++引入了ostrstream、istrstream、strstream这三个类,要使用他们创建对象就必须包含strstream.h头文件。
istrstream类用于执行C风格的串流的输入操作,也就是以字符串数组作为输入设备。
ostrstream类用于执行C风格的串流的输出操作,也就是一字符串数组作为输出设备。
strstream类同时可以支持C风格的串流的输入输出操作。
istrstream类是从istream(输入流类)和strstreambase(字符串流基类)派生而来,ostrstream是从ostream(输出流类)和strstreambase(字符串流基类)派生而来,strstream则是从iostream(输入输出流类)和和strstreambase(字符串流基类)派生而来。
他们的继承关系如下图所示:

串流同样不是标准设备,不会有预先定义好的全局对象,所以不能直接操作,需要通过构造函数创建对象。

类istrstream的构造函数原形如下:
istrstream::istrstream(const char *str,int size);
参数1表示字符串数组,而参数2表示数组大小,当size为0时,表示istrstream类对象直接连接到由str所指向的内存空间并以/0结尾的字符串。
下面的示例代码就是利用istrstream类创建类对象,制定流输入设备为字符串数组,通过它向一个字符型对象输入数据。
代码如下:

//程序作者:管宁 
//站点:www.cndev-lab.com 
//所有稿件均有版权,如要转载,请务必著名出处和作者 
#include  
#include  
using namespace std; 
int main()  

char *name = "www.cndev-lab.com"; 
int arraysize = strlen(name)+1; 
    istrstream is(name,arraysize); 
char temp; 
    is>>temp; 
cout<    system("pause"); 
}

类ostrstream用于执行串流的输出,它的构造函数如下所示:
ostrstream::ostrstream(char *_Ptr,int streamsize,int Mode = ios::out);
第一个参数是字符数组,第二个是说明数组的大小,第三个参数是指打开方式。
我们来一个示例代码:

#include  
#include  
using namespace std; 
int main()  

int arraysize=1; 
char *pbuffer=new char[arraysize]; 
    ostrstream ostr(pbuffer,arraysize,ios::out); 
    ostr<cout<delete[] pbuffer; 
    system("pause"); 
}

上面的代码中,我们创建一个c风格的串流输出对象ostr,我们将arraysize内的数据成功的以字符串的形式输出到了ostr对象所指向的pbuffer指针的堆空间中,pbuffer也正是我们要输出的字符串数组,在结尾要使用ends结束字符串,如果不这么做就有溢出的危险。

这篇关于[转]20110324-C++的iostream标准库介绍(1)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

性能测试介绍

性能测试是一种测试方法,旨在评估系统、应用程序或组件在现实场景中的性能表现和可靠性。它通常用于衡量系统在不同负载条件下的响应时间、吞吐量、资源利用率、稳定性和可扩展性等关键指标。 为什么要进行性能测试 通过性能测试,可以确定系统是否能够满足预期的性能要求,找出性能瓶颈和潜在的问题,并进行优化和调整。 发现性能瓶颈:性能测试可以帮助发现系统的性能瓶颈,即系统在高负载或高并发情况下可能出现的问题

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名

图神经网络模型介绍(1)

我们将图神经网络分为基于谱域的模型和基于空域的模型,并按照发展顺序详解每个类别中的重要模型。 1.1基于谱域的图神经网络         谱域上的图卷积在图学习迈向深度学习的发展历程中起到了关键的作用。本节主要介绍三个具有代表性的谱域图神经网络:谱图卷积网络、切比雪夫网络和图卷积网络。 (1)谱图卷积网络 卷积定理:函数卷积的傅里叶变换是函数傅里叶变换的乘积,即F{f*g}

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)