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++》第五版
原创文章 38 获赞 13 访问量 4032

猜你喜欢

转载自blog.csdn.net/qq_36287943/article/details/104518268