C++ 基础IO操作

1.基本IO库文件

C++为处理不同类型IO操作,分别在iostream中定义了用于读写流的基本类型,fstream中定义了读写文件的类型,sstream中定义了读写string对象的类型。如下所示:

  1. iostream: istream, wistream 从流读取数据
    ostream, wostream 向流写入数据
    iostream, wiostream 读写流
  2. fstream: ifstream, wifstream 从文件读取数据
    ofstream, wofstream 向文件写入数据
    fstream, wfstream 读写文件
  3. sstream: istringstream, wistringstream 从string读取数据
    ostringstream, wostringstream 向string写入数据
    stringstream, wstringstream 读写string
  4. streambuf: 流缓冲区基类,包含文件缓冲类filebuf和字符串缓冲类stringbuf

常用的类型有:

  • istream:输入流类型,提供输入操作
  • ostream:输出流类型,提供输出操作
  • cin:一个istream对象,从标准输入读取数据
  • cout:一个ostream对象,向标准输出写入数据
  • cerr:一个ostream对象,用于输出错误消息写入到标准错误
  • '>>运算符:从一个istream对象读取输入数据
  • <<运算符:向一个ostream对象写入输出数据
  • getline:从一个给定的istream读取一行数据,存入string对象中

对于操作符endl,我们知道它的作用是换行并刷新缓冲区,类似的操作符还有flush和ends,它们的作用如下:

cout<<"hello"<<endl;    //输出hello并换行,然后刷新缓冲区
cout<<"hello"<<flush;   //输出hello,然后刷新缓冲区
cout<<"hello"<<ends;    //输出hello和一个空字符,然后刷新缓冲区

注意1: IO对象不能进行拷贝或赋值

ofstream o1, o2;
o1 = o2;        //错误,不能对流对象赋值
ofstream print(ofstream)//错误,不能初始化ofstream参数
o1 = print(o1); //错误,不能拷贝流对象

1.1 操作符

标准库定义了一组操作符来修改流的格式状态,一个操作符是一个函数或对象,能用做输入或输出运算符的运算对象。操作符用于两大类输出控制:控制数值输出形式和控制补白的数量和位置。

注意2: 当操作符改变流的格式状态时,通常改变后的状态对所有后续IO都有效

  1. boolalpha操作符控制布尔值格式
cout << "default bool values: "<< true <<" " << false
    << "\nalpha bool values: "<< boolalpha << true <<" "<< false << endl;

运行得到结果如下:
default bool values: 1 0
alpha bool values: true false

  1. hex、oct、dec和showbase操作符控制整型值进制显示和输出
cout << showbase;     //显示进制
cout << "default: "<< 20 <<" "<< 1024 <<endl;        //默认十进制
cout << "octal: "<< oct << 20 <<" "<< 1024 <<endl;   //八进制
cout << "hex: " << hex << 20 <<" "<< 1024 <<endl;    //十六进制
cout << "decimal: " << dec << 20 <<" "<< 1024 <<endl;//十进制
cout << noshowbase;   //恢复流状态

运行得到结果如下:
default: 20 1024
octal: 024 02000
hex: 0x14 0x400
decimal: 20 1024

注意3: 操作符hex、oct、dec只影响整型运算对象,不影响浮点值表示

  1. precision成员、setprecision操作符指定打印精度
cout.precision(6);     //打印精度6位
cout << "precision: " << cout.precision() << ",value: " << sqrt(3.0) <<endl;
cout<<setprecision(3); //打印精度3位
cout << "precision: " << cout.precision() << ",value: " << sqrt(3.0) <<endl;

运行得到结果如下:
precision: 6,value: 1.73205
precision: 3,value: 1.73

  1. 为更好地控制数据格式,标准库提供以下操作符
  • setw:指定下一个数字或字符串值的最小空间
  • left:左对齐输出
  • right:右对齐输出,默认格式
  • internal:控制负数的符号位置,左对齐符号右对齐值,空格填满中间
  • setfill:允许指定一个字符代替默认空格输出
int a = -100;
cout << "a: " << setw(10) << a <<endl;
cout << left << "a: " << setw(10) << a <<endl;
cout << right << "a: " << setw(10) << a <<endl;
cout << internal << "a: " << setw(10) << a <<endl;
cout << setfill('#') << "a: " << setw(10) << a <<endl;

运行得到结果如下:
a:    -100
a: -100   
a:    -100
a: -  100
a: -######100


2.文件输入输出操作

标准库除了提供格式化的IO操作之外,还提供了一组底层操作来支持未格式化的IO操作,如下:

  • is.get(ch): 从istream is读取一下个字节存入字符ch并返回is

  • os.put(ch): 将字符ch输出到ostream os并返回os

  • is.get(): 将is的下一个字符作为int返回

  • is.putback(ch): 将字符ch放回is并返回is

  • is.unget(): 将is向后移动一个字节并返回is

  • is.peek(): 将下一个字节作为int返回,但不从流中删除它

  • is.get(sink,size,delim): 从is中读取最多size个字节,保存到sink为起始地址的字符数组。读取时直到遇到delim字符或读取size个字节或到文件尾停止。遇到delim不读取

  • is.getline(sink,size,delim): 与get类似,但会读取delim并丢弃

  • is.read(sink,size): 读取最多size个字节存入字符数组sink中并返回is

  • is.gcount(): 返回上一个未格式化读取操作从is读取的字节数

  • os.write(source,size): 将字符数组source中的size个字节写入os并返回os

对一个文件进行读和写操作可使用文件流对象进行,文件流对象与文件关联,每个文件流都定义了一个open的成员函数进行文件的读或写。每个流都有一个关联的文件模式,用来指出如何使用文件。

2.1 文件模式有以下几种:

  • in :以读方式打开,只可对ifstream或fstream对象设定
  • out :以写方式打开,只可对ofstream或fstream对象设定
  • app :每次写操作前都定位到文件末尾,只有trunc没设定就可设定app模式
  • ate :打开文件后立即定位到文件末尾,可用于任何类型文件流对象
  • trunc :截断文件,只有当out也设定时才可设定trunc模式
  • binary :以二进制方式进行,可用于任何类型文件流对象

基本使用如下:

ofstream out1(filename,ofstream::out);    //以输出模式打开文件并截断文件
ofstream out2(filename,ofstream::out | ofstream::trunc); //以输出模式打开文件并截断文件
ofstream app1(filename,ofstream::app);     //显式指定app模式,保留文件内容
ofstream app2(filename,ofstream::out | ofstream::app); //显式指定app模式,保留文件内容
ofstream out;   //未指定打开模式
out.open(file); //隐含输出和截断
out.close();
out.open(file1,ofstream::app);  //输出和追加
out.close();

注意4:默认情况以out模式打开文件会丢失现有数据。保留被ofstream打开的文件中数据的方式是指定app模式或in模式

2.2 输入输出运算符重载

输入运算符的第一个形参是运算符将要读取的流的引用,第二个形参是将要读入的对象的引用。
输出运算符的第一个形参是一个非常量ostream对象引用,第二个形参一般是一个常量的引用。

//输出运算符重载示例
friend std::ostream &operator<<(std::ostream &os, const Edge &edge) {
    os << edge.a << " - " << edge.b << ": " << edge.c;
    return os;
}
//输入运算符重载示例
friend std::ostream &operator>>(std::istream &is, const Edge &edge) {
    is >> edge.a >> edge.b >> edge.c;
    if(is)
        ......
    return isl
}

注意5: 输入运算符需要检查是否成功,输出运算符不需要

2.3 示例代码

ifstream file(filename); //创建文件流对象打开给定文件,open会自动调用
assert(file.is_open());  //需要判断文件是否打开成功
file.close();            //file对象使用完成之后可手动调用close关闭

// 1.获取键盘输入
string line;             //string是C++提供的字符串类
cout<<"input a line with enter: ";
getline(cin, line, '\n');
cout << line << endl;

// 2.按行读取文件内容
ifstream file(filename);        //将filename读进file中
string line;                    //按行读取
assert(file.is_open());         //判断文件是否成功打开
assert(getline(file,line));     //使用getline()读取file中的第一行放进line,再判断读取成功
stringstream ss(line);          //line放进stringstream中。对一行文本中内容进行操作时,通常可使用stringstream进行操作
                  
for(int i=0;i<N;++i){           //循环读取
    assert(getline(file, line));
    stringstream ss(line);
    int a, b;
    ss >> a >> b;               //取出ss中的两个数据到x和y
}

// 3.数值转字符串输出
ostringstream ss;
ss << 1024;                 //向stringstream中写数据
ss << " c++ ostringstream"; //向stringstream中写数据
cout << ss.str() <<endl;    //str()创建一个临时string对象将流生成字符串

// 4.向文件写入用户输入数据
ofstream os;
string line; 
os.open("file.dat", ofstream::out | ofstream::app); //写模式打开文件,保留文件并追加输出
cout<<"input a line with enter: ";
getline(cin, line, '\n');   //获取输入一行数据
os << line << endl;         //放入ofstream


References:
  • 《Primer c++》第五版
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
 一、ASCII 输出   为了使用下面的方法, 你必须包含头文件<fstream.h>(译者注:在标准C++中,已经使用<fstream>取 代< fstream.h>,所有的C++标准头文件都是无后缀的。)。这是 <iostream.h>的一个扩展集, 提供有缓 冲的文件输入输出操作. 事实上, <iostream.h> 已经被<fstream.h>包含了, 所以你不必包含所有这两个 文件, 如果你想显式包含他们,那随便你。我们从文件操作类的设计开始, 我会讲解如何进行ASCII I/O 操作。如果你猜是"fstream," 恭喜你答对了! 但这篇文章介绍的方法,我们分别使用"ifstream"?和 "ofstream" 来作输入输出。   如果你用过标准控制台流"cin"?和 "cout," 那现在的事情对你来说很简单。 我们现在开始讲输出部 分,首先声明一个类对象。 ofstream fout;   这就可以了,不过你要打开一个文件的话, 必须像这样调用ofstream::open()。 fout.open("output.txt");   你也可以把文件名作为构造参数来打开一个文件. ofstream fout("output.txt");   这是我们使用的方法, 因为这样创建和打开一个文件看起来更简单. 顺便说一句, 如果你要打开的文 件不存在,它会为你创建一个, 所以不用担心文件创建的问题. 现在就输出到文件,看起来和"cout"的操 作很像。 对不了解控制台输出"cout"的人, 这里有个例子。 int num = 150; char name[] = "John Doe"; fout << "Here is a number: " << num << " "; fout << "Now here is a string: " << name << " ";   现在保存文件,你必须关闭文件,或者回写文件缓冲. 文件关闭之后就不能再操作了, 所以只有在你 不再操作这个文件的时候才调用它,它会自动保存文件。 回写缓冲区会在保持文件打开的情况下保存文 件, 所以只要有必要就使用它。回写看起来像另一次输出, 然后调用方法关闭。像这样: fout << flush; fout.close();    现在你用文本编辑器打开文件,内容看起来是这样:   Here is a number: 150 Now here is a string: John Doe   很简单吧! 现在继续文件输入, 需要一点技巧, 所以先确认你已经明白了流操作,对 "<<" 和">>" 比较熟悉了, 因为你接下来还要用到他们。继续…   二、ASCII 输入   输入和"cin" 流很像. 和刚刚讨论的输出流很像, 但你要考虑几件事情。在我们开始复杂的内容之前 , 先看一个文本:   12 GameDev 15.45 L This is really awesome!   为了打开这个文件,你必须创建一个in-stream对象,?像这样。 ifstream fin("input.txt");   现在读入前四行. 你还记得怎么用"<<" 操作符往流里插入变量和符号吧?好,?在 "<<" (插入)?操作 符之后,是">>" (提取) 操作符. 使用方法是一样的. 看这个代码片段.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值