请选择 进入手机版 | 继续访问电脑版

[C 语言] C++之IO类,文件输入输出,string流练习 题

[复制链接]
查看134 | 回复25 | 2021-9-12 19:24:19 | 显示全部楼层 |阅读模式
目次

前面已经在用的IO库办法

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

IO类

    1. iostream
    复制代码
    头文件:从标准流中读写数据,
    1. istream
    复制代码
    ,
    1. ostream
    复制代码
    1. fstream
    复制代码
    头文件:从文件中读写数据,
    1. ifstream
    复制代码
    ,
    1. ofstream
    复制代码
    1. sstream
    复制代码
    头文件:从字符串中读写数据,
    1. istringstream
    复制代码
    ,
    1. ostringstream
    复制代码

IO对象不能拷贝或赋值

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

  • IO对象不能存在容器里.
  • 形参和返回范例 也不能是流范例 。
  • 形参和返回范例 一样寻常 是流的引用。
  • 读写一个IO对象会改变其状态,因此传递和返回的引用不能是const的。

条件状态

状态 表明
strm:iostate 是一种机器无关的范例 ,提供了表达条件状态的完备 功能
strm:badbit 用来指出流已经崩溃
strm:failbit 用来指出一个IO操作失败了
strm:eofbit 用来指出流到达了文件竣事
strm:goodbit 用来指出流未处于错误状态,此值保证为零
s.eof() 若流s的eofbit置位,则返回true
s.fail() 若流s的failbit置位,则返回true
s.bad() 若流s的badbit置位,则返回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操纵符
      1. endl
      复制代码
      :输出一个换行符并革新 缓冲区
      1. flush
      复制代码
      :革新 流,但不添加任何字符
      1. ends
      复制代码
      :在缓冲区插入空字符null,然后革新
      1. unitbuf
      复制代码
      :告诉流接下来每次操作之后都要举行 一次flush操作。
      1. nounitbuf
      复制代码
      :回到正常的缓冲方式

文件输入输出

头文件fstream定义了三个范例 来支持文件IO:

    1. ifstream
    复制代码
    从一个给定文件读取数据。
    1. ofstream
    复制代码
    向一个给定文件写入数据。
    1. 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关联的文件是否成功打开且尚未关闭

上表中,

  1. fstream
复制代码
是头文件
  1. fstream
复制代码
中定义的一个范例 ,fstrm是一个文件流对象。

文件模式

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

string流

头文件

  1. sstream
复制代码
定义了三个范例 来支持内存IO:

    1. istringstream
    复制代码
    从string读取数据。
    1. ostringstream
    复制代码
    向string写入数据。
    1. stringstream
    复制代码
    可以读写给定string。

stringstream特有的操作

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

上表中

  1. sstream
复制代码
是头文件
  1. sstream
复制代码
中恣意 一个范例 。s是一个string。

书中演示demo利用

  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. #include <sstream>
  5. using namespace std;
  6. typedef struct PersonInfo
  7. {
  8. string name;
  9. vector<string> phones;
  10. }p;
  11. int main() {
  12. string line, word;
  13. vector<p> people;
  14. while (getline(cin, line))
  15. {
  16. p info;
  17. istringstream record(line);
  18. record >> info.name;
  19. while (record >> word)
  20. info.phones.push_back(word);
  21. people.push_back(info);
  22. }
  23. for (auto i : people)
  24. {
  25. cout << i.name << endl;
  26. for (auto j : i.phones)
  27. cout << j << " ";
  28. cout << endl;
  29. }
  30. return 0;
  31. }
复制代码

练习

练习 1

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

解:

  1. std::istream& func(std::istream &is)
  2. {
  3. std::string buf;
  4. while (is >> buf)
  5. std::cout << buf << std::endl;
  6. is.clear();
  7. return is;
  8. }
复制代码

练习 2

  1. 测试函数,调用参数为cin。
复制代码

解:

  1. #include <iostream>
  2. using std::istream;
  3. istream& func(istream &is)
  4. {
  5. std::string buf;
  6. while (is >> buf)
  7. std::cout << buf << std::endl;
  8. is.clear();
  9. return is;
  10. }
  11. int main()
  12. {
  13. istream& is = func(std::cin);
  14. std::cout << is.rdstate() << std::endl;
  15. return 0;
  16. }
复制代码

测试

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. istream& f1(istream& is)
  5. {
  6. int s;
  7. while (is >> s)
  8. {
  9. cout << s << endl;
  10. }
  11. return is;
  12. }
  13. istream& f2(istream& is)
  14. {
  15. int s;
  16. while (is >> s)
  17. {
  18. cout << s << endl;
  19. }
  20. is.clear();
  21. return is;
  22. }
  23. int main()
  24. {
  25. istream& is = f1(cin);
  26. cout << is.rdstate() << endl;
  27. istream& is2 = f2(cin);
  28. cout << is2.rdstate() << endl;
  29. return 0;
  30. }
复制代码

练习 3

  1. 什么情况下,下面的while循环会终止?
复制代码
  1. while (cin >> i) /* ... */
复制代码

如badbit、failbit、eofbit 的任一个被置位,那么检测流状态的条件会失败。

练习 4

  1. 编写函数,以读模式打开一个文件,将其内容读入到一个string的vector中,将每一行作为一个独立的元素存于vector中。
复制代码
  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. #include <fstream>
  5. using namespace std;
  6. void ReadFileToVec(const string& filename, vector<string>& vec)
  7. {
  8. ifstream ifs(filename);
  9. if (ifs)
  10. {
  11. string buf;
  12. while (getline(ifs, buf))
  13. vec.push_back(buf);
  14. }
  15. }
复制代码

练习 5

  1. 重写上面的程序,将每个单词作为一个独立的元素进行存储。
复制代码
  1. void ReadFileToVec(const string& fileName, vector<string>& vec)
  2. {
  3. ifstream ifs(fileName);
  4. if (ifs)
  5. {
  6. string buf;
  7. while (ifs >> buf)
  8. vec.push_back(buf);
  9. }
  10. }
复制代码

练习 6

  1. 编写程序,将来自一个文件中的行保存在一个vector中。然后使用一个istringstream从vector读取数据元素,每次读取一个单词。
复制代码
  1. #include <iostream>
  2. #include <string>
  3. #include <sstream>
  4. #include <fstream>
  5. #include <vector>
  6. using namespace std;
  7. int main()
  8. {
  9. //将来自一个文件的行保存到vector中
  10. ifstream ifs("hello.txt");
  11. if (!ifs)
  12. {
  13. cerr << "no data ?" << endl;
  14. return -1;
  15. }
  16. vector<string> vecline;
  17. string line;
  18. while(getline(ifs, line))
  19. vecline.push_back(line);
  20. ifs.close();
  21. //从vector读取元素,每次只读一个单词
  22. for (auto &s : vecline)
  23. {
  24. istringstream iss(s);
  25. string word;
  26. while (iss >> word)
  27. cout << word << endl;
  28. }
  29. return 0;
  30. }
复制代码

练习 7

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

解:

  1. #include <iostream>
  2. #include <sstream>
  3. #include <string>
  4. #include <vector>
  5. using std::vector; using std::string; using std::cin; using std::istringstream;
  6. struct PersonInfo {
  7. string name;
  8. vector<string> phones;
  9. };
  10. int main()
  11. {
  12. string line, word;
  13. vector<PersonInfo> people;
  14. istringstream record;
  15. while (getline(cin, line))
  16. {
  17. PersonInfo info;
  18. record.clear();
  19. record.str(line);
  20. record >> info.name;
  21. while (record >> word)
  22. info.phones.push_back(word);
  23. people.push_back(info);
  24. }
  25. for (auto &p : people)
  26. {
  27. std::cout << p.name << " ";
  28. for (auto &s : p.phones)
  29. std::cout << s << " ";
  30. std::cout << std::endl;
  31. }
  32. return 0;
  33. }
复制代码

练习 8

  1. 我们为什么没有在PersonInfo中使用类内初始化?
复制代码

解:

由于 这里只必要 聚合类就够了,以是 没有必要在PersionInfo中利用 类内初始化。

练习 9

电话号码程序

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

总结

本篇文章就到这里了,盼望 可以或许 给你带来帮助,也盼望 您可以或许 多多关注脚本之家的更多内容!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

avatar 名人堂熊猫虞kk | 2021-9-12 22:02:51 | 显示全部楼层
赞一个!
回复

使用道具 举报

avatar 天蝎孤星等 | 2021-9-18 10:51:48 | 显示全部楼层
楼上的很有激情啊!
回复

使用道具 举报

avatar 司驴迁咏 | 2021-9-19 05:59:34 | 显示全部楼层
admin楼主,我告诉你一个你不知道的的秘密,有一个牛逼的网站,运动刷步数还是免费刷的,QQ和微信都可以刷,特别好用。访问地址:http://yd.mxswl.com 猫先森网络
回复

使用道具 举报

avatar 123457684 | 2021-9-19 08:25:17 | 显示全部楼层
很多天不上线,一上线就看到这么给力的帖子!
回复

使用道具 举报

avatar 123457000 | 2021-9-19 22:36:10 | 显示全部楼层
admin楼主,我告诉你一个你不知道的的秘密,有一个牛逼的网站,影视频道的网站所有电影和连续剧都可以免费看的。访问地址:http://tv.mxswl.com
回复

使用道具 举报

avatar 123457846 | 2021-10-3 08:00:37 | 显示全部楼层
今天皮痒了?
回复

使用道具 举报

avatar 快乐人L | 2021-10-5 11:01:10 | 显示全部楼层
骂人也是要有水平的!
回复

使用道具 举报

avatar 风雨狼 | 2021-10-7 06:34:51 | 显示全部楼层
admin楼主的等级很高啊!
回复

使用道具 举报

admin楼主,我告诉你一个你不知道的的秘密,有一个牛逼的网站,影视频道的网站所有电影和连续剧都可以免费看的。访问地址:http://tv.mxswl.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则