在学习C语言的时候,就已经接触到输入输出操作。但是对于C++面向对象的特性,输入输出就相对简单和安全多了。
目录
1. 引言
以前在学习c语言的时候,是用printf和scanf进行输出和输人的方法。C++与C兼容的,所以也保留了用printf和scanf进行输出和输人的方法,以便使过去所编写的大量的C程序仍然可以在C ++的环境下运行。但是C++是C的超集,有面向对象的特性,所以引入了新的输入输出。C++通过I/O类库来实现丰富的I/O功能。
2. 流
在C++中,把数据的输入和输出当作流水一样从一处流向另一处,因此将此过程称为流(Stream)。流表示了信息从源到目的端的流动。在输入操作时,字节流从输入设备(如键盘、磁盘)流向内存,在输出操作时,字节流从内存流向输出设备(如屏幕、打印机、磁盘等)。实际上,在内存中为每一个数据流开辟一个内存缓冲区,用来存放流中的数据。
3. IO流
3.1 概述
为了实现这种流动,C++定义了I/O标准类库,这些每个类都称为流/流类,用以完成某方面的功能。这里涉及到继承的概念。ios是抽象基类,由它派生出istream类和ostream类,两个类名中第1个字母i和o分别代表输入(input)和输出(output)。istream类支持输入操作,ostream类支持输出操作, iostream类支持输入输出操作。iostream类是从istream类和ostream类通过多重继承而派生的类。fstream又是iostream的派生类,它是文件的输入输出类。
对象 | 含义 | 对应设备 | c语言中相应的标准文件 |
---|---|---|---|
cin | 标准输入流 | 键盘 | stdin |
cout | 标准输出流 | 屏幕 | stdout |
cerr | 标准错误流 | 屏幕 | stderr |
clog | 标准错误流 | 屏幕 | stderr |
cin、cout、cerr、clog都是对象,注意使用的时候,展开std命名空间。有了流的概念是不是就能理解cout <<和 cin >>了,它们像流动的方向。
3.2 进阶
C++的输入输出比C语言的安全,因为C++的没有格式,而C语言的需要控制符来规定格式,比如整型要%d,字符要%c。但是C++不需要。因为C++里,在istream和ostream类(这两个类都是在iostream中声明的)中分别有一组成员函数对位移运算符“<<”和“>>”进行重载,以便能用它输入或输出各种标准数据类型的数据。对于不同的标准数据类型要分别进行重载,如:
所以系统会自动判断类型而调用相应函数。
3.3 控制符
在C语言里我们的printf是可以通过控制符格式化输出的。C++也必须有啊,不然需要相应格式怎么办?比如:
输出双精度数:后面的还有两位却没有输出出来。所以就需要控制符。
控制符 | 作 用 |
---|---|
dec | 设置数值的基数为10 |
hex | 设置数值的基数为16 |
oct | 设置数值的基数为8 |
setfill(c) | 设置填充字符c,c可以是字符常量或字符变量 |
setprecision(n) | 设置浮点数的精度为n位。在以一般十进制小数形式输出时,n代表有效数字。在以fixed(固定小数位数)形式 和 scientific(指数)形式输出时,n为小数位数 |
setw(n) | 设置字段宽度为n位 |
setiosflags( ios::fixed) | 设置浮点数以固定的小数位数显示 |
setiosftags( ios::scientific) | 设置浮点数以科学记数法(即指数形式)显示 |
setiosflags( ios::left) | 输出数据左对齐 |
setiosflags( ios::right) | 输出数据右对齐 |
setiosflags( ios::skipws) | 忽略前导的空格 |
setiosflags( ios::uppercase) | 数据以十六进制形式输出时字母以大写表示 |
setiosflags( ios::lowercase) | 数据以十六进制形式输出时宇母以小写表示 |
setiosflags(ios::showpos) | 输出正数时给出“+”号 |
这个时候我们看看。
注意使用的时候要有头文件<iomanip>。
4. 文件IO
前面说完了标准输入输出,现在来说说文件的输入输出。(C语言文件操作)可以选择对比浏览
在C++的I/O类库中定义了几种文件类,专门用于对磁盘文件的输入输出操作。在前面的图可以看到:
- ifstream类,它是从istream类派生的,用来支持从磁盘文件的输入。
- ofstream类,它是从ostream类派生的,用来支持向磁盘文件的输出。
- fstream类,它是从iostream类派生的,用来支持对磁盘文件的输入输出。
我们知道标准输入输出是cin和cout、cerr、clog对象,那么要以磁盘文件为对象进行输入输出,必须定义一个文件流类的对象,通过文件流对象将数据从内存输出到磁盘文件,或者通过文件流对象从磁盘文件将数据输入到内存。(文件流本身不是文件,而只是以文件为输入输出对象的流。)
4.1 文件的打开与关闭
操作文件的第一件事就是打开文件。文件操作完成就要关闭文件流。
- 打开:void open (const char* filename, ios_base::openmode mode = ios_base::out);
filename:文件的名称
mode :打开方式,默认是以输出方式打开文件,如果已有此名字的文件,则将其原有内容全部清除
其方式如下:注意加粗文字。
方 式 | 作用 |
---|---|
ios::in | 以输入方式打开文件 |
ios::out | 以输出方式打开文件(这是默认方式),如果已有此名字的文件,则将其原有内容全部清除 |
ios::app | 以输出方式打开文件,写入的数据添加在文件末尾 |
ios::ate | 打开一个已有的文件,文件指针指向文件末尾 |
ios: :trunc | 打开一个文件,如果文件已存在,则删除其中全部数据,如文件不存在,则建立新文件。 如已指定了 ios::out 方式,而未指定ios: :app,ios::ate,ios: :in,则同时默认此方式 |
ios:: binary | 以二进制方式打开一个文件,如不指定此方式则默认为ASCII方式 |
ios::in l ios::out | 以输入和输出方式打开文件,文件可读可写 |
ios:: out | ios::binary | 以二进制方式打开一个输出文件 |
ios::in l ios::binar | 以二进制方式打开一个输入文件 |
- 关闭:void close();
所谓关闭,实际上是解除该磁盘文件与文件流的关联,原来设置的工作方式也失效,这样,就不能再通过文件流对该文件进行输入或输出。
4.2 文件的读和写
这是对文件的操作。对于文件的读和写分为,字节流和字符流。字节流就是按二进制方式读写,字符流就是按字符串方式读写。对于文件对象,我们通常以构造方式打开。
ofstream fout (const char* filename, ios_base::openmode mode = ios_base::out)
- 字节流读写
读取:istream& read (char* s, streamsize n);
写入:ostream& write (const char* s, streamsize n);
void Practice1()
{
const char bw[] = "abcde";
ofstream fout("BinaryCin.txt");
fout.write(bw,50);
fout.close();
char br[50];
ifstream fin("BinaryCin.txt");
fin.read(br, sizeof(br));
cout << br << endl;
}
- 字符流读写
常采用如下方式
写:从ostream继承的公共成员函数;ofstream& operator<<
读:从istream继承的公共成员函数;ifstream& operator>>
void Practice2()
{
ofstream out("ChCin.txt");
out << "字符流的写入" << endl;
out << "字符流的写入" << endl;
ifstream in("ChCin.txt");
string str;
in >> str;
cout << str << endl;//只会输出一行
}
在函数中创建文件流对象,可以不用关闭,对象销毁后,自动调用析构,关闭文件流。