C/C++编程:流的基类std::basic_ios

Myth丶恋晨 2022-05-18 05:40 272阅读 0赞
  1. template <class charT, class traits = char_traits<charT> >
  2. class basic_ios;

流的基类(与类型有关的组件):管理任意流缓冲

20210303201338634.png

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3poaXpoZW5nZ3Vhbg_size_16_color_FFFFFF_t_70

模板类,用于实例化所有流类的基类

类模板在它继承的ios_base组件中添加了以下信息:






































  field 成员函数 描述
状态 填充字符 fill 字符填充格式的字段,直到 field width (width).
状态 错误状态 rdstate
setstate
clear
流的当前错误状态
单个值可以通过调用 goodeoffail 和bad.来获得。
具体见 成员类型 iostate.
异常掩码 exceptions 引发 failure 异常的状态标志
具体见 成员类型 iostate.
Other tied stream tie 指向输出流的指针,该输出流在对该流的每个I / O操作之前已刷新
流缓冲区 rdbuf 指向关联的指针 basic_streambuf 对象,负责所有输入/输出操作。

模板参数












charT 字符类型
traits 字符特征类,它定义流对象使用的字符的基本属性(请参阅char_traits

模板实例化












ios

流的基类(与类型有关的组件)(类)

wios

宽字符流的基类(类)

这些实例化在中声明 ,通过引用将其包含在

成员类型




































成员类型 描述 note
char_type 第一个模板参数(charT)  
traits_type  第二个模板参数(traits) 默认char_traits<charT>
int_type traits_type::int_type  
pos_type traits_type::pos_type 一般来说,与 streampos相同
off_type traits_type::off_type 一般来说,与  streamoff相同

以及从ios_base继承的成员类型 :




































event

表示事件类型的类型(公共成员类型)

event_callback

事件回调函数类型(公共成员类型)

failure

流异常的基类(公共成员类)

fmtflags

流格式标志的类型(公共成员类型)

Init

初始化标准流对象(公共成员类)

iostate

流状态标志的类型(公共成员类型)

openmode

流打开模式标志的类型(公共成员类型)

seekdir

流搜索方向标志的类型(公共成员类型)

--

公共成员函数












(constructor)

构造对象(公共成员函数)

(destructor)

销毁对象(公共成员函数)

构造函数
















intialization (1)    
  1. public: explicit basic_ios (basic_streambuf<char_type,traits_type>* sb);
default (2) protected: basic_ios();
copy(3) basic_ios (const basic_ios&) = delete;
basic_ios& operator= (const basic_ios&) = delete;

构造新的 basic_ios 对象

1) 以调用init(sb) 初始化内部状态。设置关联流缓冲为 sb

2)默认构造函数。不初始化内部状态。必须在首次使用对象或析构函数前调用 init() ,否则行为未定义

3)复制、拷贝构造函数被删除

状态函数






































good 检查是否没有发生错误

eof

检查是否到达了文件末尾

fail

检查是否发生了可恢复的错误

bad

检查是否已发生不可恢复的错误

operator!

检查是否有错误发生(fail() 的同义词)

operator bool 

检查是否没有发生错误(!fail()的同义词)

rdstate

返回状态标志

setstate

设置状态标志

clear

修改状态标志

std::basic_ios::good、std::basic_ios::bad、std::basic_ios::fail

  1. bool good() const;

若流未出现错误(最近 I/O 操作成功完成)则为 true ,否则为 false

  1. bool bad() const;

若关联的流上已出现不可恢复的错误则返回 true 。尤其是若 rdstate() 中设置了 badbit 则返回 true 。

设置 badbit 的条件列表见 ios_base::iostate

  1. bool fail() const;

若关联流上已发生(可恢复的)错误则返回 true 。特别是若 rdstate() 中设置了 badbitfailbit 则返回 true 。

设置 failbitbadbit 的条件列表见 ios_base::iostate 。

下表显示 basic_ios 访问器( good()、 fail() 等)对于 ios_base::iostate 标志的所有可能组合的值:











































































































ios_base::iostate 标志 basic_ios 访问器
eofbit failbit badbit good() fail() bad() eof() operator bool operator!
false false false true false false false true false
false false true false true true false false true
false true false false true false false false true
false true true false true true false false true
true false false false false false true true false
true false true false true true true false true
true true false false true false true false true
true true true false true true true false true

--

  1. // error state flags
  2. #include <iostream> // std::cout, std::ios
  3. #include <sstream> // std::stringstream
  4. void print_state (const std::ios& stream) {
  5. std::cout << " good()=" << stream.good();
  6. std::cout << " eof()=" << stream.eof();
  7. std::cout << " fail()=" << stream.fail();
  8. std::cout << " bad()=" << stream.bad();
  9. }
  10. int main () {
  11. std::stringstream stream;
  12. stream.clear (stream.goodbit);
  13. std::cout << "goodbit:"; print_state(stream); std::cout << '\n';
  14. stream.clear (stream.eofbit);
  15. std::cout << " eofbit:"; print_state(stream); std::cout << '\n';
  16. stream.clear (stream.failbit);
  17. std::cout << "failbit:"; print_state(stream); std::cout << '\n';
  18. stream.clear (stream.badbit);
  19. std::cout << " badbit:"; print_state(stream); std::cout << '\n';
  20. return 0;
  21. }

20210303205129953.png

std::basic_ios::eof

  1. bool eof()const;

检查当前 rdstate() 是否设置了eofbit:

  • 当按与流关联的顺序到达文件结束时,所有标准输入操作都会设置此标志。
  • 也就是说检查是否到达了文件末尾
  • 具体设置 eofbit 的条件列表见 ios_base::iostate 。
    -
  1. // ios::eof example
  2. #include <iostream> // std::cout
  3. #include <fstream> // std::ifstream
  4. int main () {
  5. std::ifstream is("example.txt"); // open file
  6. char c;
  7. while (is.get(c)) // loop getting single characters
  8. std::cout << c;
  9. if (is.eof()) // check for EOF
  10. std::cout << "[EoF reached]\n";
  11. else
  12. std::cout << "[error reading]\n";
  13. is.close(); // close file
  14. return 0;
  15. }

std :: basic_ios :: operator!

  1. bool operator!() const;

检查是否有错误发生

  • 若关联流上已出现错误则返回 true 。特别是若 rdstate() 中设置了 failbitbadbit 则返回 true
  • fail() 的同义词
  1. #include <iostream>
  2. #include <fstream>
  3. #include <cstdlib>
  4. int main()
  5. {
  6. std::ifstream file("test.txt");
  7. if(!file) // operator! 用于此
  8. {
  9. std::cout << "File opening failed\n";
  10. return EXIT_FAILURE;
  11. }
  12. // 典型的 C++ I/O 循环以 I/O 函数的返回值为循环控制条件,
  13. // operator bool() 用于此
  14. for(int n; file >> n; ) {
  15. std::cout << n << ' ';
  16. }
  17. std::cout << '\n';
  18. if (file.bad())
  19. std::cout << "I/O error while reading\n";
  20. else if (file.eof())
  21. std::cout << "End of file reached successfully\n";
  22. else if (file.fail())
  23. std::cout << "Non-integer data encountered\n";
  24. }

std::basic_ios::operator bool

  1. explicit operator bool() const;

检查是否没有发生错误

  • 若流无错误且已为 I/O 操作就绪则返回 true
  • !fail()的同义词
  1. // evaluating a stream
  2. #include <iostream> // std::cerr
  3. #include <fstream> // std::ifstream
  4. int main () {
  5. std::ifstream is;
  6. is.open ("test.txt");
  7. if (is) {
  8. // read file
  9. }
  10. else {
  11. std::cerr << "Error opening 'test.txt'\n";
  12. }
  13. return 0;
  14. }
  15. #include <iostream>
  16. #include <sstream>
  17. int main()
  18. {
  19. std::istringstream s("1 2 3 error");
  20. int n;
  21. std::cout << std::boolalpha << "s is " << static_cast<bool>(s) << '\n';
  22. while (s >> n) {
  23. std::cout << n << '\n';
  24. }
  25. std::cout << "s is " << static_cast<bool>(s) << '\n';
  26. }

20210303210525912.png

std :: basic_ios :: rdstate

  1. iostate rdstate() const;

返回当前错误状态

返回值

当前错误状态。它是位掩码类型,并且能是下列常量的组合:
























常量 解释
goodbit 无错误
badbit 不可恢复的流错误
failbit 输入/输出操作失败(格式化或提取错误)
eofbit 关联的输出序列已抵达文件尾

-

  1. // getting the state of stream objects
  2. #include <iostream> // std::cerr
  3. #include <fstream> // std::ifstream
  4. int main () {
  5. std::ifstream is;
  6. is.open ("test.txt");
  7. if ( (is.rdstate() & std::ifstream::failbit ) != 0 )
  8. std::cerr << "Error opening 'test.txt'\n";
  9. return 0;
  10. }
  11. #include <iostream>
  12. #include <sstream>
  13. int main()
  14. {
  15. std::ostringstream stream;
  16. if (stream.rdstate() == std::ios_base::goodbit) {
  17. std::cout << "stream state is goodbit\n";
  18. }
  19. stream.setstate(std::ios_base::eofbit);
  20. // 检查状态为准确的 eofbit (无 failbit 且无 badbit )
  21. if (stream.rdstate() == std::ios_base::eofbit) {
  22. std::cout << "stream state is eofbit\n";
  23. }
  24. }

20210303210943782.png

std::basic_ios::setstate

  1. void setstate( iostate state );

在当前已设置表之外,设置流错误状态标志 state 。实质上调用 clear(rdstate() | state) 。可能抛出异常。

参数








state 要设置的流错误状态标志。能为下列常量的组合:























常量 解释
goodbit 无错误
badbit 不可恢复的流错误
failbit 输入/输出操作失败(格式化或提取错误)
eofbit 关联的输出序列已抵达文件尾

返回值

(无)

  1. #include <iostream>
  2. #include <sstream>
  3. int main()
  4. {
  5. std::ostringstream stream;
  6. if (!stream.fail()) {
  7. std::cout << "stream is not fail\n";
  8. }
  9. stream.setstate(std::ios_base::failbit);
  10. if (stream.fail()) {
  11. std::cout << "now stream is fail\n";
  12. }
  13. if (!stream.good()) {
  14. std::cout << "and stream is not good\n";
  15. }
  16. }

20210303211322513.png

std::basic_ios::clear

  1. void clear( std::ios_base::iostate state = std::ios_base::goodbit );
  • 通过以 state 的值赋值,设置流错误状态标志。默认赋值 std::ios_base::goodbit ,它拥有的效果为清除所有错误状态标志。
  • 若 rdbuf() 为空指针(即无关联的流缓冲),则赋值 state | badbit 。可能抛出异常

参数








state 要设置的流错误状态标志。能为下列常量的组合:























常量 解释
goodbit 无错误
badbit 不可恢复的流错误
failbit 输入/输出操作失败(格式化或提取错误)
eofbit 关联的输出序列已抵达文件尾

返回值

(无)

  1. #include <iostream>
  2. #include <string>
  3. int main()
  4. {
  5. double n;
  6. while( std::cout << "Please, enter a number\n"
  7. && ! (std::cin >> n) )
  8. {
  9. std::cin.clear();
  10. std::string line;
  11. std::getline(std::cin, line);
  12. std::cout << "I am sorry, but '" << line << "' is not a number\n";
  13. }
  14. std::cout << "Thank you for entering the number " << n << '\n';
  15. }
  16. // clearing errors
  17. #include <iostream> // std::cout
  18. #include <fstream> // std::fstream
  19. int main () {
  20. char buffer [80];
  21. std::fstream myfile;
  22. myfile.open ("test.txt",std::fstream::in);
  23. myfile << "test";
  24. if (myfile.fail())
  25. {
  26. std::cout << "Error writing to test.txt\n";
  27. myfile.clear();
  28. }
  29. myfile.getline (buffer,80);
  30. std::cout << buffer << " successfully read from file.\n";
  31. return 0;
  32. }

在此示例中,myfile打开了输入操作,但我们对其执行了输出操作,因此failbit已设置。然后该示例调用清除 为了删除该标志并允许进一步的操作

格式化










copyfmt 复制格式化信息
fill 管理填充字符

std :: basic_ios :: copyfmt

  1. basic_ios& copyfmt(const basic_ios& other);

若 other 与 *this 指代同一对象,则无效果。否则复制流 other 的状态到 *this 中。以下列序列进行:

1) 传递 erase_event 为参数,调用 register_callback() 所注册的每个回调。

2) 从 other 复制所有成员对象到 *this ,除了 rdstate() 、异常掩码和 rdbuf() 。特别是复制本地环境、格式化标志、数组 std::ios_base::iword 和 std::ios_base::pword 的内容(但不是 iwordpword 指针本身)、回调和 tie 的流。

3) 传递 copyfmt_event为参数,调用 register_callback() 所注册的每个回调。

4) 从 other 复制异常掩码到 *this ,如同通过调用 exceptions(other.exceptions())

  1. // copying formatting information
  2. #include <iostream> // std::cout
  3. #include <fstream> // std::ofstream
  4. int main () {
  5. std::ofstream filestr;
  6. filestr.open ("test.txt");
  7. std::cout.fill ('*');
  8. std::cout.width (10);
  9. filestr.copyfmt (std::cout);
  10. std::cout << 40;
  11. filestr << 40;
  12. return 0;
  13. }

本示例向两者输出以相同方式格式化的数字 out还有一个文件"test.txt"

20210303212354195.png

std::basic_ios::fill












get (1) CharT fill() const;
set (2) CharT fill( CharT ch );

管理用于填充输入转换到指定宽度的填充字符。

  • 1) 返回当前的填充字符
  • 2) 设置填充字符为 ch ,返回填充字符的先前值

返回值

调用函数前的填充字符

还可以用setfill 达到同样的效果

  1. #include <iostream>
  2. #include <iomanip>
  3. int main ()
  4. {
  5. std::cout << "With default setting : " << std::setw(10) << 40 << '\n';
  6. char prev = std::cout.fill('x');
  7. std::cout << "Replaced '" << prev << "' with '"
  8. << std::cout.fill() << "': " << std::setw(10) << 40 << '\n';
  9. }

2021030321281745.png

杂项


























exceptions 管理异常掩码
imbue 设置本地环境
rdbuf 管理相关的流缓冲区
tie 管理绑定的流
narrow 窄化字符
widen 拓宽字符

std::basic_ios::exceptions












get (1) std::ios_base::iostate exceptions() const;
set(2) void exceptions( std::ios_base::iostate except );

获取和设置流的异常掩码。异常掩码确定在哪些错误状态出现时抛出 failure 类型异常。

1) 返回异常掩码。

2) 设置异常掩码为 except

  1. // basic_ios::exceptions
  2. #include <iostream> // std::cerr
  3. #include <fstream> // std::ifstream
  4. int main () {
  5. std::ifstream file;
  6. file.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
  7. try {
  8. file.open ("test.txt");
  9. while (!file.eof()) file.get();
  10. }
  11. catch (std::ifstream::failure e) {
  12. std::cerr << "Exception opening/reading file";
  13. }
  14. file.close();
  15. return 0;
  16. }
  17. #include <iostream>
  18. #include <fstream>
  19. int main()
  20. {
  21. int ivalue;
  22. try {
  23. std::ifstream in("in.txt");
  24. in.exceptions(std::ifstream::failbit);
  25. in >> ivalue;
  26. } catch (std::ios_base::failure &fail) {
  27. // 此处处理异常
  28. }
  29. }

std::basic_ios::imbue

  1. std::locale imbue( const std::locale& loc );

替换当前本地环境。等效地调用 ios_base::imbue(loc) ,而若有关联流缓冲( rdbuf() != 0 ),则再调用 rdbuf()->pubimbue(loc)

  1. #include <iostream>
  2. #include <sstream>
  3. #include <locale>
  4. int main()
  5. {
  6. std::istringstream iss;
  7. iss.imbue(std::locale("en_US.UTF8"));
  8. std::cout << "Current locale: " << iss.getloc().name() << '\n';
  9. iss.imbue(std::locale());
  10. std::cout << "Global locale : " << iss.getloc().name() << '\n';
  11. }

20210303213738820.png

std::basic_ios::rdbuf

  1. std::basic_streambuf<CharT, Traits>* rdbuf() const; (1)
  2. std::basic_streambuf<CharT, Traits>* rdbuf( std::basic_streambuf<CharT, Traits>* sb ); (2)

获取/设置流缓冲区

  • 1) 返回关联的流缓冲。若无关联流缓冲,则返回空指针。
  • 2) 设置关联流缓冲为 sb 。通过调用 clear() 清除错误状态。返回操作前的关联流缓冲。若无关联流缓冲,则返回空指针。
  1. #include <iostream>
  2. #include <sstream>
  3. int main()
  4. {
  5. std::ostringstream local;
  6. auto cout_buff = std::cout.rdbuf(); // 保存指向 std::cout 缓冲的指针
  7. std::cout.rdbuf(local.rdbuf()); // 以 'local' 对象的缓冲
  8. // 替换内部的 std::cout 缓冲
  9. // 现在 std::cout 以 'local' 缓冲工作
  10. // 你看不到此消息
  11. std::cout << "some message";
  12. // 回到旧缓冲
  13. std::cout.rdbuf(cout_buff);
  14. // 你将看到此消息
  15. std::cout << "back to default buffer\n";
  16. // 打印 'local' 内容
  17. std::cout << "local content: " << local.str() << "\n";
  18. }

20210303214025161.png

  1. // redirecting cout's output thrrough its stream buffer
  2. #include <iostream> // std::streambuf, std::cout
  3. #include <fstream> // std::ofstream
  4. int main () {
  5. std::streambuf *psbuf, *backup;
  6. std::ofstream filestr;
  7. filestr.open ("test.txt");
  8. backup = std::cout.rdbuf(); // back up cout's streambuf
  9. psbuf = filestr.rdbuf(); // get file's streambuf
  10. std::cout.rdbuf(psbuf); // assign streambuf to cout
  11. std::cout << "This is written to the file";
  12. std::cout.rdbuf(backup); // restore cout's original streambuf
  13. filestr.close();
  14. return 0;
  15. }

std::basic_ios::tie












get (1)

std::basic_ostream<CharT,Traits> tie() const;

set(2) std::basic_ostream<CharT,Traits> tie( std::basic_ostream<CharT,Traits>* str );

默认情况下,联系标准流 cincerrcout 。类似地,联系其宽对应版本 wcinwcerrwcout

获取/设置绑定流

(1)返回一个指向绑定输出流的指针。

(2)将对象绑定到tiestr,并返回指向调用之前绑定的流的指针(如果有)。

  1. // redefine tied object
  2. #include <iostream> // std::ostream, std::cout, std::cin
  3. #include <fstream> // std::ofstream
  4. int main () {
  5. std::ostream *prevstr;
  6. std::ofstream ofs;
  7. ofs.open ("test.txt");
  8. std::cout << "tie example:\n";
  9. *std::cin.tie() << "This is inserted into cout";
  10. prevstr = std::cin.tie (&ofs);
  11. *std::cin.tie() << "This is inserted into the file";
  12. std::cin.tie (prevstr);
  13. ofs.close();
  14. return 0;
  15. }

std :: basic_ios :: narrow、std::basic_ios::widen

  1. char narrow( char_type c, char dfault ) const;
  • 将结果从 char_type 转换到 char 。若不能进行转换,则函数返回 dfault
  • 等效地调用 std::use_facet< std::ctype >(getloc()).narrow(c, dfault); 。

参数












c 要转换的字符
dfault 若转化不成功则返回的字符

返回值

转换到标准等价物再到 char 的字符。若转换失败则返回 dfault

  1. char_type widen (char c) const;
  • 将结果从 char 转换到 char_type
  • 等效地调用std::use_facet< std::ctype >(getloc()).widen(c)。

受保护的成员函数




















init 初始化一个默认构造的std::basic_ios

move

(C++11)

从另一 std::basic_ios 移动,除了 rdbuf

swap

(C++11)

与另一 std::basic_ios 交换,除了 rdbuf
set_rdbuf 替换 rdbuf 而不清除其错误状态

std::basic_ios::init

  1. protected:
  2. void init( std::basic_streambuf<CharT,Traits>* sb );

设置关联流缓冲为 sb 并初始化内部状态。

后置条件如下:












































元素
rdbuf() sb
tie() 空指针
rdstate() 若 sb 不是空指针, 则为 goodbit ,否则为 badbit
exceptions() goodbit
flags() skipws | dec
width() ​0​
precision() 6
fill() widen(‘ ‘)
getloc() std::locale() 所返回的值的副本

此成员函数为受保护:一旦知晓实际缓冲区类型,则它为派生流类 std::basic_istream 和 std::basic_ostream 的构造函数所调用。直至调用此函数前,默认构造的 std::basic_ios 每个成员函数(包括析构函数)都引发未定义行为。注意 basic_ios 是虚基类,从而其构造函数不为直接派生类的构造函数所调用,此乃二阶段初始化为必须的原因。

参数








sb 要关联到的流缓冲

参阅








(构造函数)

构造对象

--

从ios_base继承的公共成员函数

#




















































flags

获取/设置格式标志(公共成员函数)

setf

设置特定的格式标志(公共成员函数)

unsetf

清除特定格式的标志(公共成员函数)

precision

获取/设置浮点十进制精度(公共成员函数)

width

获取/设置字段宽度(公共成员函数)

imbue

Imbue语言环境(公共成员函数)

getloc

获取当前语言环境(公共成员函数)

xalloc

获取可扩展数组的新索引[静态] (公共静态成员函数)

iword

获取可扩展数组的整数元素(公共成员函数)

pword

获取可扩展数组的指针元素(公共成员函数)

register_callback

注册事件回调函数(公共成员函数)

sync_with_stdio

设置每个输入输出操作后是否将标准C++流同步到标准C流

发表评论

表情:
评论列表 (有 0 条评论,272人围观)

还没有评论,来说两句吧...

相关阅读