资讯专栏INFORMATION COLUMN

【C++】IO库 : IO类,文件输入输出,string流

Youngs / 2601人阅读

摘要:输出流类型,提供输出操作一个对象,从标准输入读取数据。一个对象,向标准错误写入消息。向一个给定文件写入数据。完成这些操作后,在返回流之前,对流进行复位,使其处于有效状态。

前面已经在用的IO库设施

  • istream:输入流类型,提供输入操作。
  • ostream:输出流类型,提供输出操作
  • cin:一个istream对象,从标准输入读取数据。
  • cout:一个ostream对象,向标准输出写入数据。
  • cerr:一个ostream对象,向标准错误写入消息。
  • >>运算符:用来从一个istream对象中读取输入数据。
  • <<运算符:用来向一个ostream对象中写入输出数据。
  • getline函数:从一个给定的istream对象中读取一行数据,存入到一个给定的string对象中。

IO类

  • iostream头文件:从标准流中读写数据,istream,ostream
  • fstream头文件:从文件中读写数据,ifstream,ofstream
  • sstream头文件:从字符串中读写数据,istringstream,ostringstream

IO对象不能拷贝赋值

由于不能拷贝IO对象,因此不能将 形参 或 返回类型 设置为 流类型。进行 IO 操作的函数通常以 引用方式 传递和 返回流。读写一个IO对象会改变其状态,因此 传递和返回的引用不能用const

  • 1.IO对象不能存在容器里.
  • 2.形参和返回类型也不能是流类型。
  • 3.形参和返回类型一般是流的引用
  • 4.读写一个IO对象会改变其状态,因此传递和返回的引用不能是const的。

条件状态

状态解释
strm:iostate是一种机器无关的类型,提供了表达条件状态的完整功能
strm:badbit用来指出流已经崩溃
strm:failbit用来指出一个IO操作失败了
strm:eofbit用来指出流到达了文件结束
strm:goodbit用来指出流未处于错误状态,此值保证为零
s.eof()若流seofbit置位,则返回true
s.fail()若流sfailbit置位,则返回true
s.bad()若流sbadbit置位,则返回true
s.good()若流s处于有效状态,则返回true
s.clear()将流s中所有条件状态位复位,将流的状态设置成有效,返回void
s.clear(flags)将流s中指定的条件状态位复位,返回void
s.setstate(flags)根据给定的标志位,将流s中对应的条件状态位置位,返回void
s.rdstate()返回流s的当前条件状态,返回值类型为strm::iostate

上表中,strm是一种IO类型,(如istream), s是一个流对象。

管理输出缓冲

  • 每个输出流都管理一个缓冲区,用来保存程序读写的数据。文本串可能立即打印出来,也可能被操作系统保存在缓冲区内,随后再打印。

  • 刷新(即,数据真正写到输出设备或文件)缓冲区的IO操纵符

    • endl:输出一个换行符并刷新缓冲区
    • flush:刷新流,但不添加任何字符
    • ends:在缓冲区插入空字符null,然后刷新
    • unitbuf:告诉流接下来每次操作之后都要进行一次flush操作。
    • nounitbuf:回到正常的缓冲方式

文件输入输出

  • 头文件fstream定义了三个类型来支持文件IO:
    • ifstream从一个给定文件读取数据。
    • ofstream向一个给定文件写入数据。
    • fstream可以读写给定文件。

fstream特有的操作

操作解释
fstream fstrm;创建一个未绑定的文件流。
fstream fstrm(s);创建一个文件流,并打开名为s的文件,s可以是string也可以是char指针
fstream fstrm(s, mode);与前一个构造函数类似,但按指定mode打开文件
fstrm.open(s)打开名为s的文件,并和fstrm绑定
fstrm.close()关闭和fstrm绑定的文件
fstrm.is_open()返回一个bool值,指出与fstrm关联的文件是否成功打开且尚未关闭

上表中,fstream是头文件fstream中定义的一个类型,fstrm是一个文件流对象。

文件模式

文件模式解释
in以读的方式打开
out以写的方式打开
app每次写操作前均定位到文件末尾
ate打开文件后立即定位到文件末尾
trunc截断文件
binary以二进制方式进行IO操作。

string流

  • 头文件sstream定义了三个类型来支持内存IO:
    • istringstreamstring读取数据。
    • ostringstreamstring写入数据。
    • stringstream可以读写给定string

stringstream特有的操作

操作解释
sstream strm定义一个未绑定的stringstream对象
sstream strm(s)s初始化对象
strm.str()返回strm所保存的string的拷贝
strm.str(s)s拷贝到strm中,返回void

上表中sstream是头文件sstream中任意一个类型。s是一个string

书中演示demo使用

</>复制代码

  1. #include #include #include #include using namespace std;typedef struct PersonInfo{
  2. string name;
  3. vector phones;}p;int main() {
  4. string line, word;
  5. vector

    people;

  6. while (getline(cin, line))
  7. {
  8. p info;
  9. istringstream record(line);
  10. record >> info.name;
  11. while (record >> word)
  12. info.phones.push_back(word);
  13. people.push_back(info);
  14. }
  15. for (auto i : people)
  16. {
  17. cout << i.name << endl;
  18. for (auto j : i.phones)
  19. cout << j << " ";
  20. cout << endl;
  21. }
  22. return 0;}

练习

练习8.1

编写函数,接受一个istream&参数,返回值类型也是istream&。此函数须从给定流中读取数据,直至遇到文件结束标识时停止。它将读取的数据打印在标准输出上。完成这些操作后,在返回流之前,对流进行复位,使其处于有效状态。

解:

</>复制代码

  1. std::istream& func(std::istream &is){ std::string buf; while (is >> buf) std::cout << buf << std::endl; is.clear(); return is;}

练习8.2

测试函数,调用参数为cin

解:

</>复制代码

  1. #include using std::istream;istream& func(istream &is){ std::string buf; while (is >> buf) std::cout << buf << std::endl; is.clear(); return is;}int main(){ istream& is = func(std::cin); std::cout << is.rdstate() << std::endl; return 0;}

测试

</>复制代码

  1. #include #include using namespace std;istream& f1(istream& is){
  2. int s;
  3. while (is >> s)
  4. {
  5. cout << s << endl;
  6. }
  7. return is;}istream& f2(istream& is){
  8. int s;
  9. while (is >> s)
  10. {
  11. cout << s << endl;
  12. }
  13. is.clear();
  14. return is;}int main(){
  15. istream& is = f1(cin);
  16. cout << is.rdstate() << endl;
  17. istream& is2 = f2(cin);
  18. cout << is2.rdstate() << endl;
  19. return 0;}

练习8.3

什么情况下,下面的while循环会终止?

</>复制代码

  1. while (cin >> i) /* ... */

badbitfailbiteofbit 的任一个被置位,那么检测流状态的条件会失败。

练习8.4

编写函数,以读模式打开一个文件,将其内容读入到一个stringvector中,将每一行作为一个独立的元素存于vector中。

</>复制代码

  1. #include #include #include #include using namespace std;void ReadFileToVec(const string& filename, vector& vec){
  2. ifstream ifs(filename);
  3. if (ifs)
  4. {
  5. string buf;
  6. while (getline(ifs, buf))
  7. vec.push_back(buf);
  8. }}

练习8.5

重写上面的程序,将每个单词作为一个独立的元素进行存储。

</>复制代码

  1. void ReadFileToVec(const string& fileName, vector& vec){ ifstream ifs(fileName); if (ifs) { string buf; while (ifs >> buf) vec.push_back(buf); }}

练习8.10

编写程序,将来自一个文件中的行保存在一个vector中。然后使用一个istringstreamvector读取数据元素,每次读取一个单词。

</>复制代码

  1. #include #include #include #include #include using namespace std;int main(){
  2. //将来自一个文件的行保存到vector中
  3. ifstream ifs("hello.txt");
  4. if (!ifs)
  5. {
  6. cerr << "no data ?" << endl;
  7. return -1;
  8. }
  9. vector vecline;
  10. string line;
  11. while(getline(ifs, line))
  12. vecline.push_back(line);
  13. ifs.close();
  14. //从vector读取元素,每次只读一个单词
  15. for (auto &s : vecline)
  16. {
  17. istringstream iss(s);
  18. string word;
  19. while (iss >> word)
  20. cout << word << endl;
  21. }
  22. return 0;}

练习8.11

本节的程序在外层while循环中定义了istringstream对象。如果record对象定义在循环之外,你需要对程序进行怎样的修改?重写程序,将record的定义移到while循环之外,验证你设想的修改方法是否正确。

解:

</>复制代码

  1. #include #include #include #include using std::vector; using std::string; using std::cin; using std::istringstream;struct PersonInfo { string name; vector phones;};int main(){ string line, word; vector people; istringstream record; while (getline(cin, line)) { PersonInfo info; record.clear(); record.str(line); record >> info.name; while (record >> word) info.phones.push_back(word); people.push_back(info); } for (auto &p : people) { std::cout << p.name << " "; for (auto &s : p.phones) std::cout << s << " "; std::cout << std::endl; } return 0;}

练习8.12

我们为什么没有在PersonInfo中使用类内初始化?

解:

因为这里只需要聚合类就够了,所以没有必要在PersionInfo中使用类内初始化。

练习8.13

电话号码程序

</>复制代码

  1. #include #include #include #include #include using namespace std;struct PersonInfo {
  2. string name;
  3. vector phones;};bool valid(const string& str){
  4. return isdigit(str[0]);}string format(const string& str){
  5. return str.substr(0, 3) + "-" + str.substr(3, 3) + "-" + str.substr(6);}int main(){
  6. //从文件中读取信息存入vector容器
  7. ifstream ifs("phone.txt");
  8. if (!ifs)
  9. {
  10. cerr << "no phone numbers ? " << endl;
  11. return -1;
  12. }
  13. vector people;
  14. string line, word;
  15. istringstream record;
  16. while (getline(ifs, line))
  17. {
  18. PersonInfo info;
  19. record.clear();
  20. record.str(line);
  21. record >> info.name;
  22. while (record >> word)
  23. {
  24. info.phones.push_back(word);
  25. }
  26. people.push_back(info);
  27. }
  28. //逐个验证电话号码 并 改变其格式
  29. for (const auto& entry : people) //对people中的每一项
  30. {
  31. //每个循环创建的对象
  32. ostringstream formatted, badnums;
  33. //对每个数
  34. for (const auto& nums : entry.phones)
  35. {
  36. if (!valid(nums))
  37. {
  38. badnums << " " << nums;
  39. //将数的字符串形式存入badnums
  40. }
  41. else
  42. {
  43. //将格式化的字符串写入formatted
  44. formatted << " " << format(nums);
  45. }
  46. }
  47. //没有错误的数
  48. if (badnums.str().empty())
  49. {
  50. cout << entry.name << " "
  51. << formatted.str() << endl;
  52. }
  53. else
  54. {
  55. //打印名字和错误的数
  56. cerr << "input error: " << entry.name
  57. << " invalid number(s)" << badnums.str() << endl;
  58. }
  59. }
  60. return 0;}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/119673.html

相关文章

  • [C/C++]C++IO

    摘要:二中流的概念中的流是对一种有序连续且具有方向性的数据的抽象描述。用来进行标准错误的输出。在使用时候必须要包含文件并引入标准命名空间。实际是在其底层维护了一个类型的对象用来保存结果。可以使用将让返回其底层的对象。  本文对比了C语言的输入与输出,介绍了流的概念、C++IO流以及stringst...

    Lin_R 评论0 收藏0
  • C++IO详解

    摘要:在使用时候必须要包含头文件并引入标准命名空间。在该头文件下,标准库三个类进行流的输入进行流的输出进行流的输入输出将结构体的内容转换成字符串字符串的内容输出到结构体当中注意实际是在其底层维护了一个类型的对象用来保存结果。 ...

    trilever 评论0 收藏0
  • 2018年第一周-Java的IO系统

    摘要:过滤器流,如等,是类库,是为了提供一些类让你能够处理一些极为常见的数据格式。读写器,由于流和过滤器流还是仅次于处理字节,也就是二进制。过滤器流缓冲流和类将写入的数据存储到缓冲区中一个名为的保护字节数组字段,直到缓冲区满或刷新输出流。 A little older, a little wiser, but happy to see you. ——Interstellar 2018年了,再...

    kgbook 评论0 收藏0
  • 从设计者的角度理解Java IO

    摘要:通过多个装饰类实现责任链模式,它将对一个输入流的不同处理分散到不同的中去。 1、基本概念 1.1、InputStream 最基本的字节输入流,抽象类,定义了读取原始字节的所有基本方法1.1.1、public abstract int read() throws IOException 读取一个字节的方法,最基础的方法1.1.2、public int read(byte b[], in...

    Flink_China 评论0 收藏0
  • 1、Properties集合 2、序列化与反序列化 3、打印 4、commons-IO

    摘要:集合的特点集合的特点类介绍类表示了一个持久的属性集。可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串特点的子类,集合中的方法都可以用。该集合没有泛型。键值可以存储到集合中,也可以存储到持久化的设备硬盘盘光盘上。 01Properties集合的特点 * A: Properties集合的特点 * a: Properties类介绍 * Propert...

    aboutU 评论0 收藏0

发表评论

0条评论

Youngs

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<