C++基础5:文件

本文深入探讨C++中的流,包括标准I/O流、文件流和字符串流的类型及其用法。详细阐述了流对象的状态管理、I/O操作的格式控制,如进制、宽度、对齐和填充等,并介绍了整数、浮点数和布尔类型的输出格式。此外,还讲解了C++文件读写的基本流程,文件流对象的打开、关闭及读写操作,以及如何实现文件重定向和日志模块。
摘要由CSDN通过智能技术生成

1、流

流:数据从一个对象到另一个对象的传输
功能:标准输入输出+文件管理

分类含义
文本流一串ASCII字符
二进制流一串二进制

2、流类型

标准库定义了三大类流类型:标准I/O流、文件流、字符串流

2.1 标准I/O流

1、ios是抽象类
2、ostream是cout、clog、cerr的类
3、istream是cin的类

2.2 文件流类型

1、ifstream从文件读取数据
2、ofstream向文件写入数据
3、iofstream文件读写数据

2.3 字符串流类型

1、istringstream从string读取数据
2、ostringstream向string写入数据
3、iostringstream读写string数据

3、流对象

通常标准I/O流对象是全局对象不需要定义,而文件流对象和字符串流对象虚需要用户定义
标准I/O流对象有以下四个:

No.全局流对象名称缓存
1cout标准输出流带缓存
2cin标准输入流带缓存
3clog标准日志流带缓存
4cerr标准错误流无缓存

注意:流对象通常不能复制

4、流对象状态

流对象状态在某一时刻必定处于以下四个状态之一:

No.状态含义
1good()前一个流操作成功
2eof()到输入尾/文件尾
3fail()发生意外的事情(读取失败)
4bad()发生意外严重的事情(磁盘读取失败)

5、I/O操作

I/O操作主要有如下五种:
1、输入操作:in>>x或者getline(in,s)
2、输出操作:out<<x
3、操作符
4、流状态
5、格式化

5.1 输出流默认配置

类型进制宽度对齐填充精度
整数十进制0右对齐空格1
实数十进制0右对齐空格6位数
字符串0右对齐空格字符串实际长度

5.2 格式控制

(1)格式控制成员函数

流对象.格式控制函数(实参)

(2)预定义格式控制函数

预定义格式控制函数(实参)

(3)流的输出控制格式

作用格式控制成员函数预定义格式控制函数预定义格式控制符/操作子效果持续
进制flag() setf() unsetf()setiosflags()dec oct hex showbase能持续
宽度width()setw()不能持续
对齐flags() setf() unsetf()setioflags()right left internal能持续
填充fill©setfill©能持续
精度precision(n)setprecision(n)能持续

流的输出控制格式:dex,oct,hex
数据输入成员函数:
字符输入成员函数:get()
字符串输入成员函数:getline()
数据输出成员函数:put()

5.3 对齐方式

flagmanipulator作用
ios::leftleft居左
ios::rightright居右
ios::internalinternal输出符号或进制后填充

(1)成员函数方式

#include <iostream>

using namespace std;


int main(){
    int n=-11;
    cout.width(6);
    cout.flags(ios::right);
    cout << n << endl;

    cout.width(6);
    cout.flags(ios::left);
    cout << n << endl;

    cout.width(6);
    cout.flags(ios::internal);
    cout << n << endl;
}

输出结果:

   -11
-11   
-   11

(2)操作子方式

#include <iostream>
#include <iomanip>
using namespace std;


int main(){
    int n=-11;
    cout << setw(6) << right << n << endl;
    cout << setw(6) << left << n << endl;
    cout << setw(6) << internal << n << endl;

}

输出结果:

   -11
-11   
-   11

(3)混合方式

#include <iostream>
using namespace std;

int main(){
    int n=-11;
    cout.width(6); cout << left << n << endl;
    cout.width(6); cout << right << n << endl;
    cout.width(6); cout << internal << n << endl;
}

输出结果:

   -11
-11   
-   11

5.4 整数输出格式

flagmanipulator作用是否默认
ios::decdec十进制
ios::octoct八进制
ios::hexhex十六进制
ios::upperccaseuppercase使用大写输出十六进制
ios::showbaseshowbase输出带有进制的字符

(1)成员函数方式

#include <iostream>

using namespace std;
int main(){
    int n=-11;
    cout.flags(ios::dec);
    cout << n << endl;
    cout.flags(ios::hex);
    cout << n << endl;
    cout.flags(ios::oct);
    cout << n << endl;

    cout.flags(ios::showbase|ios::dec);
    cout << n << endl;
    cout.flags(ios::showbase|ios::oct);
    cout << n << endl;
    cout.flags(ios::showbase|ios::hex);
    cout << n << endl;

    cout.flags(ios::showbase|ios::uppercase|ios::dec);
    cout<<n<<endl;
    cout.flags(ios::showbase|ios::uppercase|ios::oct);
    cout<<n<<endl;
    cout.flags(ios::showbase|ios::uppercase|ios::hex);
    cout<<n<<endl;
}

输出结果:

-11
fffffff5
37777777765
-11
037777777765
0xfffffff5
-11
037777777765
0XFFFFFFF5

(2)操作子方式

#include <iostream>
using namespace std;

int main(){
    int n=-11;
    cout << dec << n << endl;
    cout << hex << n << endl;
    cout << oct << n << endl;


    cout << showbase << dec << n << endl;
    cout << oct << n << endl;
    cout << hex << n << endl;

    cout << uppercase << dec << n << endl;
    cout << oct << n << endl;
    cout << hex << n << endl;
}

输出结果:

-11
fffffff5
37777777765
-11
037777777765
0xfffffff5
-11
037777777765
0XFFFFFFF5

5.5 浮点数输出格式

flag作用是否默认精度
ios::defaultfloat默认浮点数格式最多保留多少位数字
ios::scientific科学技术法输出浮点数小数点后最多保留多少位数字
ios::fixed定点数方式输出实数小数点后最多保留多少位数字

如果浮点数没有小数时默认不显示小数点,使用ios::showpoint可以强制输出浮点数时,必须带小数点。

定点数方式比浮点数方式更精确
取浮点数精确度时,设置ios::fixed

(1)成员函数方式

#include <iostream>     // cout, std::fixed, std::scientific
using namespace std;
int main () {
  double a = 3.1415926534;
  double b = 2006.0;
  double c = 1.0e-10;

  cout.precision(5);
  cout << "default:\n";
  cout << a << endl << b << endl << c << endl;
  
  cout << "fixed:\n";
  cout.flags(ios::fixed);
  cout << a << endl << b << endl << c << endl;

  cout << "scientific:\n";
  cout.flags(ios::scientific);
  cout << a << endl << b << endl << c << endl;

  return 0;
}

输出结果:

default:
3.1416
2006
1e-10
fixed:
3.14159
2006.00000
0.00000
scientific:
3.14159e+00
2.00600e+03
1.00000e-10

(2)操作子方式

#include <iostream>
#include <iomanip>
using namespace std;

int main(){
    double a = 3.1415926534;
    double b = 2006.0;
    double c = 1.0e-10;

    cout<< setprecision(5)
    << "default:\n"
    << a << endl << b << endl << c <<endl;

    cout << "fixed:\n"<<fixed
    << a << endl << b << endl << c <<endl;

    cout << "scientific:\n"<<scientific
    << a << endl << b << endl << c <<endl;

    return 0;
}

输出结果:

default:
3.1416
2006
1e-10
fixed:
3.14159
2006.00000
0.00000
scientific:
3.14159e+00
2.00600e+03
1.00000e-10

(3)混合方式

#include <iostream>
#include <iomanip>
using namespace std;

int main(){
    double a = 3.1415926534;
    double b = 2006.0;
    double c = 1.0e-10;

    std::cout.precision(5);
    std::cout << "default:\n";
    std::cout << a << endl << b << endl << c <<endl << endl;

    std::cout<<"fixed:\n" <<std::fixed;
    std::cout << a << endl << b << endl <<c <<endl << endl;

    std::cout << "scientific:\n" <<std::scientific;
    std::cout << a << endl << b << endl << c << endl << endl;

    return 0;
}

输出结果:

default:
3.1416
2006
1e-10
fixed:
3.14159
2006.00000
0.00000
scientific:
3.14159e+00
2.00600e+03
1.00000e-10

5.5 布尔类型输出格式

flagmanipulator作用默认
ios::boolalphaboolalpha把bool值以字符串true/false输出

5.6 其他

flagmanipulator作用默认
ios::showposshowpos输出十进制0或者正数时,带+号

(1)成员函数方式

#include <iostream>

using namespace std;

int main(){
    int p=1;
    int z=0;
    int n=-1;

    cout.setf(ios::showpos);
    cout << p << '\t' << z << '\t' << n << endl;
    cout.unsetf(ios::showpos);
    cout << p << '\t' << z << '\t' << n << endl;
    return 0;
}

输出结果:

+1	+0	-1
1	0	-1

(2)操作子方式

#include <iostream>

using namespace std;

int main(){
    int p=1;
    int z=0;
    int n=-1;

    cout<<showpos << p << '\t' << z << '\t' << n << endl;
    cout<<noshowpos << p << '\t' << z << '\t' << n << endl;
    return 0;
}

输出结果:

+1	+0	-1
1	0	-1

复数虚部a+bi使用showpos非常合适

5.7 注意

最新版C++的iostream库中,在使用setiosflags()前要先使用resetiosflags()清除旧有相应信息。

cout << resetiosflags(ios::basefield)<< setiosflags(ios::hex) << 10 << endl;

以下三类格式化在使用setiosflags(),要先使用resetiosflags()清除旧有相应信息。
在这里插入图片描述

5.8 stringstream

(1)字符串转化数字

istringstream iss(str);
int n;
iss >> n;

(2)C++11提供如下函数简化字符串转数字

stoi() stol() stoul() stoll() stoull()
stof() stod() stold()

(3)数字转化字符串

int n;
ostringstream oss;
oss << n;
oss.str();

5.9 练习

(1)leecode

字符串转换整数(atoi)

(2)实现空格分割字符串

vector<string> split(const string& str){
    vector<string> res;
    istringstream iss(str);
    string s;
    while(iss >> s){
        res.push_back(s);
    }
    return res;
}

6、C++文件读写

文件:文件名+文件内容(有序数据集合)
文件名:字符序列
文件数据格式:二进制文本/文本文件

6.1 C++文件操作流程

1、打开文件
2、读写文件
3、关闭文件

6.2 打开/关闭文件

操作代码
定义读文件流对象ifstream读文件流对象
定义写文件流对象ofstream
定义读写文件流对象fstream读写读文件流对象
成员函数打开文件文件流对象.open(文件名,文件打开方式)
构造函数打开文件文件流类 对象(文件名,文件打开方式)
判断文件是否打开!文件流对象
关闭文件文件流对象.close(变量)

6.3 文本文件读写

操作代码
提取运算符读文件文件流对象>>变量
插入运算符写文件文件流对象<<变量
成员函数读文件文件流对象.get(变量)
成员函数写文件文件流对象.put(变量)

6.4 二进制文件读写

操作代码
读函数read()
写函数write()
测试文件结束eof()

6.5 文件打开方式

类型代码
ios::in
ios::out
添加末尾ios::app
已存在文件ios::nocreae
未打开文件ios::noreplace
二进制ios::binary

6.6 文件对象指针位置函数

操作代码
获取读位置对象.tellg()
获取写位置对象.tellp()
设置读位置对象.seekg()
设置写位置对象.seekp()

函数后缀p表述put(输出),后缀g表示get(输入)。
如果文件是以ios::app文本追加方式打开,指针位置默认在文件结束,其他情况默认在文件开头

6.7 文件对象状态函数

操作代码
判断文件对象状态是否正常对象.good()
重置文件对象状态对象.clear()

7、流文件类型

1、stream流文件
2、文件指针FILE*

7.1 流文件读写

(1)ifstream文件读

ifstream fin(文件路径);
fin >> 变量
fin.close();

(2)ofstream文件写

ofstream fout(文件路径);
fout << 变量
fout.close();

(3)fstream文件写

fstream fs(文件路径,ios::in|ios::out|ios::app);
if(fs){
  fs << 变量;
  fs.seekg(ios::beg);
  fs >> 变量;
  fs.close();
}

(4)fstream的打开模式是否创建不存在的文件

No.打开模式是否创建不存在的文件
1ios::in
2ios::out
3ios::inios::out
4ios::inios::out

(5)先读后写

#include <iostream>
#include <fstream>
using namespace std;

int main(){
    fstream fs("text.txt",ios::in|ios::out|ios::app);
    if(fs){
        string str;
	while(fs>>str){
	    cout << str << endl;
	}
	fs.clear();
	while(cin>>str){
	    fs<< str << endl;
	}
    }
}

输出结果:

[root@westos_student70 05:文件]# ./a.out 
qwe
qwe
[root@westos_student70 05:文件]# cat text.txt 
qwe
qwe

(6)先写后读

#include <iostream>
#include <fstream>

using namespace std;

int main(){
    fstream fs("test.txt",ios::in|ios::out|ios::app);
    if(fs){
        string str;
	while(cin >> str){
	    fs << str << endl;
	}
	fs.seekg(ios::beg);
	while(fs >> str)
	    cout << str << endl;
    }else{
        cerr << "file not exist" << endl;
    }
}

7.2 文件指针FILE读写

(1)FILE文件指针读

FILE* fp = fopen(文件路径,"r");
fscanf(,fp);
fclose(fp);

(2)FILE文件指针写

FILE* fp = fopen(文件路径,"w");
fprintf(,fp);
fclose(fp); 

对象的序列化和反序列化
序列化:把对象转化成文本/二进制
反序列化:把文本/二进制转化成对象

7.3 文件重定向

freopen(文件路径,操作,标准IO)

操作:读(r)写(w)

(1)重定向写

freopen("out.txt","w",stdout);
cout << "out data" <<endl;

(2)重定向读

freopen("in.txt","r",stdin);
string str;
cin >> str;

(3)几种常见的文件读取方式对比

ifstream + fin
freopen+cin+sync_with_stdio(false)
FILE* + fscanf
freopen+scanf
freopen+cin

(4)实现日志模块

freopen("test.log","w",stderr);
cerr << "FATAL";
cerr << "ERROR";
clog << "WARNING";
clog << "INFO";
clog << "DEBUG";
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值