8.1

 #include <iostream>
#include <string>
#include <sstream>
#include <fstream> int main()
{
//cout是一个输出流对象,位于std空间,cin是一个输入流对象
std::cout << "Hello C++ Primer" << std::endl;
std::string word;
std::cin >> word;
std::fstream fs;//fs是一个fstream对象
std::stringstream ss;//ss是一个stringstream对象
return ;
}

IO类型间的关系

C++语言不直接处理输入输出,而是通过一族定义在标准库中的类型来处理IO,这些类型支持从设备读取、向设备写入数据的IO操作,设备可以是文件,控制台窗口等。这些类型定义在三个独立的头文件中:iostream,fstream,sstream.9个标准库类型(宽字符版本算在统一的普通版本中),继承关系如下

IO对象不能拷贝或赋值

 void print(std::ofstream of)
{
std::cout << "IO test " << std::endl;
}
void print_re(std::ofstream& of)
{
std::cout << "IO referience or pointer" << std::endl;
}
 std::ofstream print(std::ofstream& of)
{
std::cout << "IO referience or pointer" << std::endl;
std::ofstream of2;
return of2;
}
 int main()
{
//cout是一个输出流对象,位于std空间,cin是一个输入流对象
std::cout << "Hello C++ Primer" << std::endl;
std::string word;
std::cin >> word;
std::fstream fs;//fs是一个fstream对象
std::stringstream ss;//ss是一个stringstream对象
//IO对象不能赋值,下面的赋值操作是错误的
std::ofstream out1;
std::ofstream out2;
out1 = out2;
//IO对象也不能拷贝
print(cout);//由于传值是拷贝操作,而IO对象不能拷贝,所以这样写是错误的
//但IO操作可以通过引用或指针传递和返回流
print_re(cout);
return ;
}

由于IO对象不能拷贝,所以不能放到对象中,因为保存在容器中的对象都必须可以复制

8.1.2 条件状态

IO操作一个与生俱来的问题就是可能发生错误,IO类定义了一些函数和标志,可以帮助我们访问和操纵流的条件状态。badbit:系统级错误,通常情况下,一旦badbit被置位,流就无法使用了。failbit,eofbit,被置位,还可以修正,流还可以继续使用。

 int ival;
std::cin >> ival;

如上述要求输入一个int型变量,若输入一个char型,则读操作就会失败,cin就会进入错误状态

 void check_cin_state(std::istream& is)
{
if (is.bad())
std::cout << "cin is bad" << std::endl;
else
std::cout << "cin is not bad" << std::endl;
if (is.fail())
std::cout << "cin is fail" << std::endl;
else
std::cout<<"cin is not fail" << std::endl;
if (is.eof())
std::cout << "cin is eof" << std::endl;
else
std::cout << "cin is not eof" << std::endl;
if (is.good())
std::cout << "cin is good" << std::endl;
else
std::cout << "cin is not good" << std::endl;
}
int main()
{
std::cout << "check the state of cin" << std::endl;
check_cin_state(std::cin);
std::cout << "please input an integer" << std::endl;
int a;
std::cin >> a;
std::cout << "check the state of cin again" << std::endl;
check_cin_state(std::cin);
system("pause");
return ;
}

要求输入的是int型,输入char型,流状态是fail。

管理流状态

上述一旦流状态is notgood就结束了,可以通过恢复流状态继续使用流

计算输入数字的和的程序为例、

 int sum = ;
int ival;
/*while (std::cin >> ival)
{
sum += ival;
std::cout << "sum is " << sum << std::endl;
}*/
//上述写法一旦输入类型不是int型就结束了,所以可以通过管理流使得流可以继续使用
while (std::cin >> ival, !std::cin.eof())
{
if (std::cin.bad())
throw std::runtime_error("IO stream is not successful");
if (std::cin.fail())
{
std::cout << "IO stream is fail,try again" << std::endl;
std::cin.clear();//恢复流状态
std::cin.ignore(, '\n');
continue;
}
sum += ival;
std::cout << "sum is " << sum << std::endl;
}
8.2 文件输入输出
头文件fstream定义了三个类型来支持文件IO:ifstream 从 一个给定文件读取数据ofstream向一个给定文件写入数据,发stream可以读写给定文件。
8.2.1文件流的使用
创建文件流对象时,如果提供了文件名,会自动调用open函数打开文件
 ofstream outfile("test.txt");//创建一个输出流对象outfile,并使用该对象创建一个文件
outfile << "Hello C++" << endl;//使用流向文件写入内容
outfile.close();//关闭流
string txt("t.txt");//文件夹中需要有此文件
ifstream infile(txt);//C++11新标准,旧版本需使用C风格字符串infile(txt.c_str())

如果定义了一个了一个空文件(文件流对象没有绑定文件),可以调用open将它与文件关联起来如果调用失败,failbit会被置位,所以进行是否成功检查是一个好习惯

 ifstream infile;
infile.open("t.txt");
if (infile)
{
string str;
while(infile >> str)
cout << str << endl;
infile.close();
}

 8.3 string流

sstream 头文件定义的三个类型是支持内存IO,即字符串流是内存中的输入输出。

istringstream从string读取数据,ostringstream向string读数据stringstream既可以从string读数据也可以向string写数据。

使用istringstream

当某些工作需要处理某行文本中的单个单词时通常可以使用istringstream

教材中有这样一个例子,家丁一个通讯录文件,列出了一些人和他们的电话,但是有些人会有不止一个电话号码,通常文件的每条记录(每一行)都是以人名开头,后面跟随他们的电话

eg: 小王   130xxxxxxxx  6283xxxx

小李   158xxxxxxxx

那么首先需要定义一个类PersonInfo来描述输入数据,PersonInfo有一个对象name来表示人名,一个vector<string>来保存电话号码。该程序需要读取兵处理多条PersonInfo记录,所以需要一个vector<PersonInfo>来保存多条记录,使用getline函数读取每一行,使用istringstream读取行中的单个单词。

 struct PersonInfo {
std::string name;
std::vector<std::string> phone;
void save_contacts();
}; void PersonInfo::save_contacts()
{
string line;//保存来自输入的一行记录
string word;//保存记录的单个单词
vector<PersonInfo> person;//保存输入的所有记录 while (getline(std::cin, line))//
{
PersonInfo info;//创建一个PersonInfo的对象,保存记录
istringstream record(line);//创建一个isrting流对象record,并绑定到输入的记录的行
record >> info.name;//读取一条记录中的名字给PersonInfo对象的name成员
while (record >> word)//读到的记录中的电话号码给PersonInfo对象的phone成员
info.phone.push_back(word);
person.push_back(info);//将读到的所有记录保存到vector<PersonInfo>中
}
}

使用ostringstream

 //使用ostringstream对构造好的输入的记录进行输出
for (const auto entry : person)
{
//创建ostring对象用于输出无效的电话号码和规范为特定格式的后的电话号码
ostringstream badNums;
ostringstream formatted;
//
for (const auto& nums : entry.phone)
{
if (!valid(nums))
badNums << " " << nums;
else
formatted << " " << format(nums);
}
if (badNums.str.empty())//如果电话号码有效,输出格式化后的电话号码
cout << entry.name << " " << formatted.str();
else
cerr << "input error :" << endl;
}

上面的是处理的从cin读取的数据,可以综合文件流和string流实现从文件读取数据

小结

C++使用标准库类来处理面向流的输入输出

iostream 处理控制台IO

fstream 处理命令文件IO

stringstream完成内存string的IO

继承关系如上面的图

每个IO对象都维护一组条件状态,用来指出此对象上是否可进行IO操作,如果遇到了错误,则对象状态变为失效,除非纠正错误才能执行后续操作

CH8 IO库的更多相关文章

  1. [APUE]标准IO库(下)

    一.标准IO的效率 对比以下四个程序的用户CPU.系统CPU与时钟时间对比 程序1:系统IO 程序2:标准IO getc版本 程序3:标准IO fgets版本 结果: [注:该表截取自APUE,上表中 ...

  2. [APUE]标准IO库(上)

    一.流和FILE对象 系统IO都是针对文件描述符,当打开一个文件时,即返回一个文件描述符,然后用该文件描述符来进行下面的操作,而对于标准IO库,它们的操作则是围绕流(stream)进行的. 当打开一个 ...

  3. 文件IO函数和标准IO库的区别

    摘自 http://blog.chinaunix.net/uid-26565142-id-3051729.html 1,文件IO函数,在Unix中,有如下5个:open,read,write,lsee ...

  4. 【转载】C++ IO库

    本篇随笔为转载,原贴地址:<C++ Primer>第8章 IO库 学习笔记. 1.IO类 #include <iostream> istream//从流中读取数据 ostrea ...

  5. 从Decorator,Adapter模式看Java的IO库

    我想任何一本介绍模式的书在讲到Decorator模式的时候不能不提到它的实际应用--在Java/IO库里面的应用,<<Java与模式>>这本书也不例外,有点不一样的是,这本书在 ...

  6. C++ Primer 读书笔记: 第8章 标准IO库

    第8章 标准IO库 8.1 面向对象的标准库 1. IO类型在三个独立的头文件中定义:iostream定义读写控制窗口的类型,fstream定义读写已命名文件的类型,而sstream所定义的类型则用于 ...

  7. 标准模板库——IO库

    IO库设施: . istream(输入流)类型,提供输入操作. . ostream(输出流)类型,提供输出操作. . cin,一个istream对象,从标准输入读取数据. . cout,一个ostre ...

  8. 高级UNIX环境编程5 标准IO库

    标准IO库都围绕流进进行的 <stdio.h><wchar.h> memccpy 一般用汇编写的 ftell/fseek/ftello/fseeko/fgetpos/fsetp ...

  9. IO库

    IO类 C++语言不直接处理出入输出,而是通过一族定义在标准库中的类型来处理IO.这些类型支持从设备读取数据.向设备写入数据的IO操作,设备可以是文件 .控制台窗口 等.还有一些类型允许内存IO ,即 ...

随机推荐

  1. 理解Linux内核注释

    内核是Linux的心脏,它是在引导时装入的程序,用来提供用户层程序和硬件之间的接口,执行发生在多任务系统中的实际任务转换,处理读写磁盘的需求,处理网络接口,以及管理内存.一般情况下,自动安装的内核无需 ...

  2. ubuntu 16 “无法获得锁”解决方案

    强制解锁,命令 sudo rm /var/cache/apt/archives/lock sudo rm /var/lib/dpkg/lock

  3. C - Water The Garden

    It is winter now, and Max decided it's about time he watered the garden. The garden can be represent ...

  4. wx小程序笔记

    目录 p18 事件绑定1 p19 事件绑定2 btn p20+ view 相关,wxss,less,css 零基础玩转微信小程序[黑马程序员] https://www.bilibili.com/vid ...

  5. FTP 上传下载 进度条

    11 /// <summary> /// 文件上传 /// </summary> /// <param name="filePath">原路径( ...

  6. 【PAT甲级】1067 Sort with Swap(0, i) (25 分)

    题意: 输入一个正整数N(<=100000),接着输入N个正整数(0~N-1的排列).每次操作可以将0和另一个数的位置进行交换,输出最少操作次数使得排列为升序. AAAAAccepted cod ...

  7. float元素上-margin的用法

    css标准,float元素上的负margin表示把下面的元素向对应方向移动,并且覆盖上一个元素(这里是指html中元素的声明顺序). 标准情况下我们用float 时候是这样的. -margin通俗点说 ...

  8. Win32 开发记录

    Typedefs LPCSTR = char* LPCWSTR = wchar_t* Webpages Control reference: https://docs.microsoft.com/en ...

  9. Vue日常报错

    报错信息: Error: Cannot find module 'webpack/bin/config-yargs' at Function.Module._resolveFilename (inte ...

  10. c++多态性及多态的内部实现(翁恺c++公开课[23-24])

    多态是在父类函数的前面加上 “virtual” 关键字,使子类与父类同名的函数产生一种联系: 多态会用到两个特性:向上造型.动态绑定 向上造型是指:拿一个子类对象当作父类来看待,比如下边代码中的子类E ...