IO类
IO对象不能拷贝和赋值
iostream
表示形式的变化:
将100转换成二进制序列 然后格式化输出
x,y共用一块内存 输出的时候用不同的方式解析同一块内存
操作
格式化:内部表示转换为相应字节序列
缓存:要输出的内容放到缓存
编码转换:字符编码转换 utf8变长编码
传输:传输给外设
输入相反
封装特性
输入与输出
非格式化IO:不涉及数据任何形式的变化
格式控制
std::ios_base
是 C++ 标准库中定义基本输入输出流的类。showpos
是std::ios_base
类中的一个标志,表示在输出正数时显示正号。std::cout.setf()
用于设置格式标志,将showpos
标志设置为std::cout
的格式掩码中,以启用显示正号的功能。std::cout.width()
是 C++ 标准库中用于设置输出宽度的成员函数。它是std::ostream
类的成员函数,用于影响后续输出的格式。这个函数接受一个整数参数,指定输出字段的宽度,以确保输出的内容在指定的宽度内。如果输出的内容长度不足 10 个字符,将在左侧用空格进行填充std::cout.fill()
是 C++ 标准库中用于设置填充字符的成员函数。它是std::ostream
类的成员函数,用于指定在宽度设置时所使用的填充字符。填充字符是用于在输出字段宽度不足时进行填充的字符。
#include<iostream>int main(){char x='1';std::cout.setf(std::ios_base::showpos); //开启正号std::cout<<x<<std::endl; int y=static_cast<int>(x);std::cout<<y<<std::endl;return 0;
}
操纵符
std::setw(int n)
: 设置字段宽度,影响后续输出的宽度。
std::setprecision(int n)
: 设置输出流的浮点数精度。
std::setiosflags(std::ios_base::fmtflags flags)
: 设置一组格式标志。
"格式提取"(format extraction)
通常指的是从输入流中读取特定格式的数据。在C++中,常用的输入操作符(如>>
)用于从输入流中提取数据,并根据期望的格式进行解析。
提取C风格字符串越界
解决方法使用setw
最后一个元素是\0
例题
#include<iostream>int main() {int i = 10;// 循环,从标准输入读取整数while (std::cin >> i, !std::cin.eof()) {// 检查是否发生了不可恢复的流错误if (std::cin.bad()) {throw std::runtime_error("cin is corrupted");}// 检查是否发生了格式错误(例如用户输入的不是整数)if (std::cin.fail()) {// 清除流的错误标志std::cin.clear();// 忽略输入缓冲区中的剩余字符,直到遇到换行符为止std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');std::cout << "data format error, please try again" << std::endl;continue;}std::cout << i << std::endl;}return 0;
}
文件流与文件操作
文件流对象
文件流处于打开就无法再次打开(C++规定) 只有打开才能IO
#include <iostream>
#include <fstream>int main() {// 打开名为 "myfile" 的文件,创建一个输入文件流对象 inFilestd::ifstream inFile("myfile");// 声明一个字符串变量 x,用于存储从文件中读取的内容std::string x;// 从文件中读取一个字符串,并将其存储到变量 x 中inFile >> x;// 输出 "hello" 到标准输出流(控制台)std::cout << "hello\n";// 关闭文件流(自动在程序结束时关闭,但显式关闭是一种好的实践)inFile.close();return 0;
}
检测是否打开的函数(检测流是否与文件关联)
打开文件:构造函数 ,或者open
关闭文件:析构函数 或者close
文件流的打开模式
每种文件流都有缺省打开方式
ate与app区别
ate开始位于文件末尾 但可以移动文件指针改变位置
app不能改变一直在文件末尾
例题
//让客户输入文件名称,如果文件不存在,就让客户重新输入文件名称,
//如果文件存在,就将文件全部内容输出。
#include<iostream>
#include<fstream>
#include <string>int main(){
//让客户输入文件名称,如果文件不存在,就让客户重新输入文件名称,
//如果文件存在,就将文件全部内容输出。std::string fileName;std::string fileContent;while(std::cin>>fileName,!std::cin.eof()){if(std::cin.bad()){throw std::runtime_error("cin is corrupted");}std::ifstream ifs(fileName);if(ifs){while(std::getline(ifs,fileContent)){std::cout<<fileContent<<std::endl;}if(ifs.bad()){throw std::runtime_error("ifs is corrupted");}ifs.close();}else{ifs.clear();ifs.ignore(std::numeric_limits<std::streamsize>::max(),'\n' );std::cout<<"file not exist,please try again"<<std::endl;continue;}}return 0;
}
内存流(stringstream)
在 C++ 中,内存流是一种特殊的流,它不与文件直接关联,而是与内存缓冲区关联。主要的内存流类是 std::istringstream
(用于输入操作)和 std::ostringstream
(用于输出操作),它们都是基于 std::iostream
类的。
1. std::istringstream
(输入内存流):
2. std::ostringstream
(输出内存流):
#include <iostream>
#include <sstream>int main() {// 创建一个输出内存流对象 obj1std::ostringstream obj1;// 将整数 1234 写入内存流obj1 << 1234;// 获取内存流中的字符串std::string res = obj1.str();// 输出字符串结果到标准输出std::cout << res << std::endl; // 输出:1234// 创建一个输入内存流对象 obj2std::istringstream obj2;int x;// 试图从内存流中读取整数obj2 >> x;return 0;
}
1. std::ostringstream::str()
:
在 std::ostringstream
中,str()
函数返回内存流中的字符串,即当前流中的内容。它允许你将输出到内存流的数据以字符串的形式获取。
2. std::istringstream::str()
:
在 std::istringstream
中,str()
函数返回内存流中的字符串,即当前流中的内容。不过,对于 std::istringstream
,str()
函数返回的是从当前读取位置到流末尾的剩余部分的字符串。
作用:
基于字符串流的拼接优化操作
数据转换
string转换为int
#include<iostream>
#include<sstream>
#include<fstream>
#include <string>int main(){std::string str("12");std::stringstream strStream(str);int i=0;strStream>>i;if(strStream.bad()){throw std::runtime_error("strStream is corrupted");}else if(strStream.fail()){strStream.clear();strStream.ignore(std::numeric_limits<std::streamsize>::max(),'\n' );std::cout<<"string format error"<<std::endl;}else{std::cout<<i<<std::endl;}return 0;
}
int转换为string
#include<iostream>
#include<sstream>
#include<fstream>
#include <string>int main(){int i=100;std::stringstream str;str<<i<<std::endl;if(str.bad()){throw std::runtime_error("str is corrupted");}else{std::cout<<str.str()<<std::endl;}return 0;
}
用于对空格分隔的字符串的切分
#include<iostream>
#include<sstream>
#include<fstream>
#include <string>int main(){std::string src("hello word");std::string des;std::stringstream str(src);while(str>>des){std::cout<<des<<std::endl;}if(str.bad()){throw std::runtime_error("str is corrupted");}return 0;
}
流的状态
badbit
:
-
badbit
是std::ios_base
类的成员之一,用于表示底层流发生了严重错误的标志。 -
当
badbit
被设置时,表示底层流已经处于无法恢复的错误状态,通常涉及到底层设备或文件的严重故障。 -
如果
badbit
被设置,流的状态会变为bad
,可以通过调用std::ios_base::bad()
函数检查。
failbit
:
-
failbit
是std::ios_base
类的成员之一,用于表示流操作失败的标志。 -
当
failbit
被设置时,表示流的操作没有按照预期执行,可能包括格式错误或类型转换失败等。 -
如果
failbit
被设置,流的状态会变为fail
,可以通过调用std::ios_base::fail()
函数检查。
复位流状态
捕获流异常
流的定位
获取流位置
tellg
是 C++ 中输入流(std::istream
)的成员函数,用于获取当前读取位置的位置指针(stream position indicator)的位置。它返回一个表示位置的整数类型,通常是 std::streampos
。
tellp
是 C++ 中输出流(std::ostream
)的成员函数,用于获取当前写入位置的位置指针(stream position indicator)的位置。它返回一个表示位置的整数类型,通常是 std::streampos
。
设置流位置
seekg
是 C++ 中输入流(std::istream
)的成员函数,用于设置当前读取位置的位置指针(stream position indicator)。这个函数允许你在输入流中移动位置,以便在需要的时候从不同的位置读取数据。
seekp
是 C++ 中输出流(std::ostream
)的成员函数,用于设置当前写入位置的位置指针(stream position indicator)。这个函数允许你在输出流中移动位置,以便在需要的时候从不同的位置写入数据
流的同步
sync
是 C++ 中 std::ostream
的成员函数,用于将缓冲区的内容刷新到关联的输出设备(例如文件)。在 C++ 的输出流中,数据通常首先被写入到缓冲区,然后通过 sync
函数将缓冲区的内容刷新到实际的输出设备。
unitbuf
是一个影响输出流缓冲行为的I/O流操纵符。具体而言,它设置流的 unitbuf
标志,这意味着在每次插入操作之后都会刷新缓冲区。
cout有缓冲区 cerr没有
基于绑定的同步(tie)
tie
是一个用于设置关联(或绑定)两个流的成员函数。这个函数是定义在 <iostream>
头文件中的。
输出流(如 std::cout
)和输入流(如 std::cin
)通常是独立的,它们各自维护自己的缓冲区。然而,有时候你可能希望确保在读取输入之前或在输出后,缓冲区被刷新,以确保数据的正确同步。这时候,tie
就可以派上用场。
tie
的作用是将一个流与另一个流关联,从而在关联的流执行某些操作时,另一个流的缓冲区会被刷新。通常,tie
绑定的是输入流和输出流。
与C语言标准IO库同步
sync_with_stdio
是一个用于控制 C 标准输入输出库(stdio)的函数,用于设置 C 标准输入输出库的缓冲同步状态。这个函数的原型通常在头文件 <stdio.h>
中声明。
sync_with_stdio
接受一个整数参数 sync
,如果 sync
的值为非零(例如,传入 1
),则表示启用缓冲同步;如果 sync
的值为零,则表示禁用缓冲同步。缓冲同步是指标准输入(stdin
)、标准输出(stdout
)、标准错误输出(stderr
)的缓冲同步状态
在这个示例中 关闭了同步 输出结果只要是a在c前面就是对的 b不一定
代码
#include<iostream>
#include<fstream>
#include <string>int main(){
//让客户输入文件名称,如果文件不存在,就让客户重新输入文件名称,
//如果文件存在,就将文件全部内容输出。std::string fileName;std::string fileContent;while(std::cin>>fileName,!std::cin.eof()){if(std::cin.bad()){throw std::runtime_error("cin is corrupted");}std::ifstream ifs(fileName);if(ifs){while(std::getline(ifs,fileContent)){std::cout<<fileContent<<std::endl;}if(ifs.bad()){throw std::runtime_error("ifs is corrupted");}ifs.close();}else{ifs.clear();ifs.ignore(std::numeric_limits<std::streamsize>::max(),'\n' );std::cout<<"file not exist,please try again"<<std::endl;continue;}}return 0;
}