C++ 的 iostream 标准库介绍 (2)
接下来我们继续看一下 C++ 风格的串流控制, C++ 引入了 ostringstream,istringstream,stringstream 这三个类, 要使用他们创建对象就必须包含 sstream.h 头文件.
istringstream 类用于执行 C++ 风格的串流的输入操作.
stringstream 类同时可以支持 C++ 风格的串流的输入输出操作.
strstream 类同时可以支持 C 风格的串流的输入输出操作.
istringstream 类是从 istream(输入流类) 和 stringstreambase(c++ 字符串流基类) 派生而来, ostringstream 是从 ostream(输出流类) 和 stringstreambase(c++ 字符串流基类) 派生而来, stringstream 则是从 iostream(输入输出流类) 和和 stringstreambase(c++ 字符串流基类) 派生而来.
他们的继承关系如下图所示:
istringstream 是由一个 string 对象构造而来, istringstream 类从一个 string 对象读取字符.
istringstream 的构造函数原形如下:
- istringstream::istringstream(string str);
- // 程序作者: 管宁
- // 站点: www.cndev-lab.com
- // 所有稿件均有版权, 如要转载, 请务必著名出处和作者
- #include <iostream>
- #include <sstream>
- using namespace std;
- int main()
- {
- istringstream istr;
- istr.str("1 56.7",);
- // 上述两个过程可以简单写成 istringstream istr("1 56.7");
- cout << istr.str()<<endl;
- int a;
- float b;
- istr>>a;
- cout<<a<<endl;
- istr>>b;
- cout<<b<<endl;
- system("pause");
- }
上例中, 构造字符串流的时候, 空格会成为字符串参数的内部分界, 例子中对 a,b 对象的输入 "赋值" 操作证明了这一点, 字符串的空格成为了整型数据与浮点型数据的分解点, 利用分界获取的方法我们事实上完成了字符串到整型对象与浮点型对象的拆分转换过程.
str() 成员函数的使用可以让 istringstream 对象返回一个 string 字符串 (例如本例中的输出操作 (cout<<istr.str();).
ostringstream 同样是由一个 string 对象构造而来, ostringstream 类向一个 string 插入字符.
ostringstream 的构造函数原形如下:
ostringstream::ostringstream(string str);
示例代码如下:
- // 程序作者: 管宁
- // 站点: www.cndev-lab.com
- // 所有稿件均有版权, 如要转载, 请务必著名出处和作者
- #include <iostream>
- #include <sstream>
- #include <string>
- using namespace std;
- int main()
- {
- ostringstream ostr;
- //ostr.str("abc");// 如果构造的时候设置了字符串参数, 那么增长操作的时候不会从结尾开始增加, 而是修改原有数据, 超出的部分增长
- ostr.put('d');
- ostr.put('e');
- ostr<<"fg";
- string gstr = ostr.str();
- cout<<gstr;
- system("pause");
- }
在上例代码中, 我们通过 put() 或者左移操作符可以不断向 ostr 插入单个字符或者是字符串, 通过 str() 函数返回增长过后的完整字符串数据, 但值得注意的一点是, 当构造的时候对象内已经存在字符串数据的时候, 那么增长操作的时候不会从结尾开始增加, 而是修改原有数据, 超出的部分增长.
对于 stringstream 了来说, 不用我多说, 大家也已经知道它是用于 C++ 风格的字符串的输入输出的.
stringstream 的构造函数原形如下:
stringstream::stringstream(string str);
示例代码如下:
- // 程序作者: 管宁
- // 站点: www.cndev-lab.com
- // 所有稿件均有版权, 如要转载, 请务必著名出处和作者
- #include <iostream>
- #include <sstream>
- #include <string>
- using namespace std;
- int main()
- {
- stringstream ostr("ccc");
- ostr.put('d');
- ostr.put('e');
- ostr<<"fg";
- string gstr = ostr.str();
- cout<<gstr<<endl;
- char a;
- ostr>>a;
- cout<<a
- system("pause");
- }
除此而外, stringstream 类的对象我们还常用它进行 string 与各种内置类型数据之间的转换.
示例代码如下:
- // 程序作者: 管宁
- // 站点: www.cndev-lab.com
- // 所有稿件均有版权, 如要转载, 请务必著名出处和作者
- #include <iostream>
- #include <sstream>
- #include <string>
- using namespace std;
- int main()
- {
- stringstream sstr;
- //--------int 转 string-----------
- int a=100;
- string str;
- sstr<<a;
- sstr>>str;
- cout<<str<<endl;
- //--------string 转 char[]--------
- sstr.clear();// 如果你想通过使用同一 stringstream 对象实现多种类型的转换, 请注意在每一次转换之后都必须调用 clear() 成员函数.
- string name = "colinguan";
- char cname[200];
- sstr<<name;
- sstr>>cname;
- cout<<cname;
- system("pause");
- }
接下来我们来学习一下输入 / 输出的状态标志的相关知识, C++ 中负责的输入 / 输出的系统包括了关于每一个输入 / 输出操作的结果的记录信息. 这些当前的状态信息被包含在 io_state 类型的对象中. io_state 是一个枚举类型 (就像 open_mode 一样), 以下便是它包含的值.
goodbit 无错误
Eofbit 已到达文件尾
failbit 非致命的输入 / 输出错误, 可挽回
badbit 致命的输入 / 输出错误, 无法挽回
有两种方法可以获得输入 / 输出的状态信息. 一种方法是通过调用 rdstate() 函数, 它将返回当前状态的错误标记. 例如, 假如没有任何错误, 则 rdstate() 会返回 goodbit.
下例示例, 表示出了 rdstate() 的用法:
- // 程序作者: 管宁
- // 站点: www.cndev-lab.com
- // 所有稿件均有版权, 如要转载, 请务必著名出处和作者
- #include <iostream>
- using namespace std;
- int main()
- {
- int a;
- cin>>a;
- cout<<cin.rdstate()<<endl;
- if(cin.rdstate() == iOS::goodbit)
- {
- cout<<"输入数据的类型正确, 无错误!"<<endl;
- }
- if(cin.rdstate() == ios_base::failbit)
- {
- cout<<"输入数据类型错误, 非致命错误, 可清除输入缓冲区挽回!"<<endl;
- }
- system("pause");
- }
另一种方法则是使用下面任何一个函数来检测相应的输入 / 输出状态:
- bool bad();
- bool eof();
- bool fail();
- bool good();
下例示例, 表示出了上面各成员函数的用法:
- // 程序作者: 管宁
- // 站点: www.cndev-lab.com
- // 所有稿件均有版权, 如要转载, 请务必著名出处和作者
- #include <iostream>
- using namespace std;
- int main()
- {
- int a;
- cin>>a;
- cout<<cin.rdstate()<<endl;
- if(cin.good())
- {
- cout<<"输入数据的类型正确, 无错误!"<<endl;
- }
- if(cin.fail())
- {
- cout<<"输入数据类型错误, 非致命错误, 可清除输入缓冲区挽回!"<<endl;
- }
- system("pause");
- }
如果错误发生, 那么流状态既被标记为错误, 你必须清除这些错误状态, 以使你的程序能正确适当地继续运行. 要清除错误状态, 需使用 clear() 函数. 此函数带一个参数, 它是你将要设为当前状态的标志值., 只要将 iOS::goodbit 作为实参.
示例代码如下:
- // 程序作者: 管宁
- // 站点: www.cndev-lab.com
- // 所有稿件均有版权, 如要转载, 请务必著名出处和作者
- #include <iostream>
- using namespace std;
- int main()
- {
- int a;
- cin>>a;
- cout<<cin.rdstate()<<endl;
- cin.clear(iOS::goodbit);
- cout<<cin.rdstate()<<endl;
- system("pause");
- }
通常当我们发现输入有错又需要改正的时候, 使用 clear() 更改标记为正确后, 同时也需要使用 get() 成员函数清除输入缓冲区, 以达到重复输入的目的.
示例代码如下:
- // 程序作者: 管宁
- // 站点: www.cndev-lab.com
- // 所有稿件均有版权, 如要转载, 请务必著名出处和作者
- #include <iostream>
- using namespace std;
- int main()
- {
- int a;
- while(1)
- {
- cin>>a;
- if(!cin)// 条件可改写为 cin.fail()
- {
- cout<<"输入有错! 请重新输入"<<endl;
- cin.clear();
- cin.get();
- }
- else
- {
- cout<<a;
- break;
- }
- }
- system("pause");
- }
最后再给出一个对文件流错误标记处理的例子, 巩固学习, 代码如下:
- // 程序作者: 管宁
- // 站点: www.cndev-lab.com
- // 所有稿件均有版权, 如要转载, 请务必著名出处和作者
- #include <iostream>
- #include <fstream>
- using namespace std;
- int main()
- {
- ifstream myfile("c:\\1.txt",ios_base::in,0);
- if(myfile.fail())
- {
- cout<<"文件读取失败或指定文件不存在!"<<endl;
- }
- else
- {
- char ch;
- while(myfile.get(ch))
- {
- cout<<ch;
- }
- if(myfile.eof())
- {
- cout<<"文件内容已经全部读完"<<endl;
- }
- while(myfile.get(ch))
- {
- cout<<ch;
- }
- }
- system("pause");
- }
来源: http://www.bubuko.com/infodetail-3124045.html