- 流类体系
- 流:数据从一个对象到另一个对象的传输。
- 功能:标准输入输出+文件处理
分类 | 含义 |
---|---|
文本流 | 一串ASCII字符 |
二进制流 | 一串二进制 |
* ios
是抽象类
* ostream
是cout
、clog
、cerr
的类
* istream
是cin
的类
全局流对象 | 名称 | 缓存 |
---|---|---|
cout | 标准输出流 | 带缓存 |
cin | 标准输入流 | 带缓存 |
clog | 标准日志流 | 带缓存 |
cerr | 标准错误流 | 无缓存 |
- 输出流默认设置
类型 | 进制 | 宽度 | 对齐 | 填充 | 精度 |
---|---|---|---|---|---|
整数 | 十进制 | 0 | 右对齐 | 空格 | 1 |
实数 | 十进制 | 0 | 右对齐 | 空格 | 6位数 |
字符串 | - | 0 | 右对齐 | 空格 | 字符串实际长度 |
* 格式控制
* 格式控制成员函数
流对象.格式控制函数(实参)
- 预定义格式控制函数
预定义格式控制函数(实参)
- 流的输出控制格式
作用 | 格式控制成员函数 | 预定义格式控制函数 | 预定义格式控制符/操作子 |
---|---|---|---|
进制 | flags() setf() unsetf() | setiosflags() | dec oct hex showbase |
宽度 | width(n) | setw(n) | - |
对齐 | flags() setf() unsetf() | setiosflags() | right left internal |
填充 | fill(c) | setfill(c) | - |
精度 | precision(n) | setprecision(n) | - |
* 流的输出控制格式:dec
oct
hex
* 数据输入成员函数
字符输入成员函数:get()
字符串输入成员函数:getline()
* 数据输出成员函数:put()
对齐方式
flag | manipulator | 作用 |
---|---|---|
ios::left | left | 居左 |
ios::right | right | 居右 |
ios::internal | internal | 输出符号或进制后填充 |
#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;
}
#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;
}
#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;
}
整数输出格式
flag | manipulator | 作用 | 是否默认 |
---|---|---|---|
ios::dec | dec | 十进制 | 是 |
ios::oct | oct | 八进制 | 否 |
ios::hex | hex | 十六进制 | 否 |
ios::uppercase | uppercase | 使用大写输出十六进制 | 否 |
ios::showbase | showbase | 输出带有进制的字符 | 否 |
#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;
}
#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;
}
浮点数八进制/十六进制输出结果?
flag | 作用 | 是否默认 |
---|---|---|
ios::showpoint | 输出浮点数时,必须带小数点 | 否 |
浮点数输出格式
flag | 作用 | 是否默认 |
---|---|---|
ios::scientific | 科学计数法输出浮点数 | 否 |
ios::fixed | 定点数方式输出实数 | 是 |
定点数方式比浮点数方式更精确
取浮点数精确度时,设置ios::fixed
#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;
}
#include <iostream> // std::cout, std::fixed, std::scientific
#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;
}
#include <iostream> // std::cout, std::fixed, std::scientific
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 << '\n' << b << '\n' << c << '\n\n'
std::cout << "fixed:\n" << std::fixed;
std::cout << a << '\n' << b << '\n' << c << '\n\n'
std::cout << "scientific:\n" << std::scientific;
std::cout << a << '\n' << b << '\n' << c << '\n\n';
return 0;
}
布尔类型输出格式
flag | manipulator | 作用 |
---|---|---|
ios::boolalpha | boolalpha | 把bool 值以字符串true /false 输出 |
flag | manipulator | 作用 |
---|---|---|
ios::showpos | showpos | 输出十进制0或者正数时,带+号 |
#include <iostream> // std::cout, std::showpos, std::noshowpos
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;
}
#include <iostream> // std::cout, std::showpos, std::noshowpos
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;
}
字符串转化数字
istringstream iss(str);
int n;
iss >> n;
C++11提供如下函数简化字符串转数字
*stoi()
stol()
stoul()
stoll()
stoull()
*stof()
stod()
stold()
数字转化字符串
int n;
ostringstream oss;
oss << n;
oss.str();
string
字符串遍历
string str("abcdefg");
- C写法
for(size_t i=0;i<str.size();i++){
cout << str[i] << endl;
}
- 迭代器写法
for(string::iterator it = str.begin();it != str.end();it++){
cout << *it << endl;
}
- STL
for_each
写法
void print(char c){
cout << c << endl;
}
for_each(str.begin(),str.end(),print);
- C++11迭代器写法
for(string::iterator it = begin(str);it != end(str);it++){
cout << *it << endl;
}
或者
for(auto it = begin(str);it != end(str);it++){
cout << *it << endl;
}
- C++11 for新语法写法
for(char c : str){
cout << c << endl;
}
或者
for(auto c : str){
cout << c << endl;
}
- C++11 STL
for_each
与lamdba表达式
for_each(begin(str),end(str),[](char c){cout << c << endl;});
向量遍历
vector<int> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
vec.push_back(4);
vec.push_back(5);
- C写法
for(size_t i=0;i<vec.size();i++){
cout << vec[i] << endl;
}
- 迭代器写法
for(vector<int>::iterator it = vec.begin();it != vec.end();it++){
cout << *it << endl;
}
- STL
for_each
写法
void print(int n){
cout << n << endl;
}
for_each(vec.begin(),vec.end(),print);
- C++11迭代器写法
for(vector<int>::iterator it = begin(vec);it != end(vec);it++){
cout << *it << endl;
}
或者
for(auto it = begin(vec);it != end(vec);it++){
cout << *it << endl;
}
- C++11 for新语法写法
for(int n : vec){
cout << n << endl;
}
或者
for(auto n : vec){
cout << n << endl;
}
- C++11 STL
for_each
与lamdba表达式
for_each(begin(vec),end(vec),[](int n){cout << n << endl;});
C++文件读写
文件:文件名+文件内容(有序数据集合)
文件名:字符序列
文件数据格式:二进制文件/文本文件C++文件操作流程
- 打开文件
- 读写文件
- 关闭文件
打开/关闭文件
操作 | 代码 |
---|---|
定义读文件流对象 | ifstream 读文件流对象 |
定义写文件流对象 | ofstream 写读文件流对象 |
定义读写文件流对象 | fstream 读写读文件流对象 |
成员函数打开文件 | 文件流对象.open(文件名,文件打开方式) |
构造函数打开文件 | 文件流类 对象(文件名,文件打开方式) |
判断文件是否打开 | !文件流对象 |
关闭文件 | 文件流对象.close(变量) |
* 文本文件读写
操作 | 代码 |
---|---|
提取运算符读文件 | 文件流对象 >> 变量 |
插入运算符写文件 | 文件流对象 << 变量 |
成员函数读文件 | 文件流对象.get(变量) |
成员函数写文件 | 文件流对象.put(变量) |
* 二进制文件读写
操作 | 代码 |
---|---|
读函数 | read() |
写函数 | write() |
测试文件结束 | eof() |
* 文件打开方式
类型 | 代码 |
---|---|
读 | ios::in |
写 | ios::out |
添加末尾 | ios::app |
已存在文件 | ios::nocreate |
未打开文件 | ios::noreplace |
二进制 | ios::binary |
* 文件对象指针位置函数
操作 | 代码 |
---|---|
获取读位置 | 对象.tellg() |
获取写位置 | 对象.tellp() |
设置读位置 | 对象.seekg() |
设置写位置 | 对象.seekp() |
如果文件是以
ios::app
文本追加方式打开,指针位置默认在文件结束,其他情况默认在文件开头。
- 文件对象状态函数
操作 | 代码 |
---|---|
判断文件对象状态是否正常 | 对象.good() |
重置文件对象状态 | 对象.clear() |
流式文件类型
1. stream
流文件
2. 文件指针FILE*
stream
流文件读写
ifstream
文件读
ifstream fin(文件路径);
fin >> 变量
fin.close();
ofstream
文件写
ofstream fout(文件路径);
fout << 变量
fout.close();
fstream
文件写
fstream fs(文件路径);
if(!fs){
fs << 变量;
fs.tellp(ios::beg);
fs >> 变量;
fs.close();
}
文件指针FILE
读写
FILE
文件指针读
FILE* fp = fopen(文件路径,"r");
fscanf(,fp);
fclose(fp);
FILE
文件指针写
FILE* fp = fopen(文件路径,"w");
fprintf(,fp);
fclose(fp);
对象的序列化与反序列化
序列化:把对象转化成文本/二进制
反序列化:把文本/二进制转化成对象
文件重定向
freopen(文件路径,操作,标准IO)
操作:读(w
) 写(r
)
- 重定向写
freopen("out.txt","w",stdout);
cout << "out data" <<endl;
- 重定向读
freopen("in.txt","r",stdin);
string str;
cin >> str;
几种常见的文件读取方式对比
* ifstream
+ fin
* freopen
+cin
+sync_with_stdio(false)
* FILE*
+ fscanf
* freopen
+scanf
* freopen
+cin
实现日志模块
日志:记录程序日常运行状态。按条记录,记录内容包括:时间、模块、日志级别(致命、出错、警告、信息、调试)、输出位置(文件、终端、系统日志)
日志信息格式
yyyy-mm-dd hh-MM-ss [Level] module file:line func:message
日志文件名格式
yyyy-mm-dd-XXXX.log
yyyy-mm-dd-XXXX2.log
配置文件格式
文件名:log.conf
内容:
level=ERROR,INFO或者ALL
path=XXXX/xxxx
module=ALL或者XXXX
backlog=date/file
backlog-size=10d/100M
max-size=1G
接口
FATAL(module,str);
ERROR(module,str);
WARNING(module,str);
INFO(module,str);
DEBUG(module,str);
性能
1. 控制日志输出位置
2. 控制日志输出级别
3. 控制日志输出模块
4. 是否支持多线程
5. 日志备份(按日期、按大小),设置备份数量
6. 设置最大日志文件大小
特殊功能
终端输出不同级别颜色不同
危险红
警告黄
信息蓝
默认黑
freopen("test.log","w",stderr);
cerr << "FATAL";
cerr << "ERROR";
clog << "WARNING";
clog << "INFO";
clog << "DEBUG";