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. Spring Boot Log 日志使用教程

    我们编写任何 Spring Boot 程序,可能绕不开的就是 log 日志框架(组件). 在大多数程序员眼中日志是用来定位问题的.这很重要. 本项目源码下载 注意本项目提供的源码已在后期重新编写,有部 ...

  2. cemtos安装python

    mkdir python3cd python3/yum -y install gcc*yum install zlib-devel bzip2-devel openssl-devel ncurses- ...

  3. DOCKER SNAT与DNAT

    映射容器端口到宿主主机的实现 默认情况下,容器可以主动访问到外部网络的连接,但是外部网络无法访问到容器. 容器访问外部实现 容器所有到外部网络的连接,源地址都会被 NAT 成本地系统的 IP 地址.这 ...

  4. CRS-1硬件维护

    一.CRS-1硬件介绍CRS-1 路由器是Cisco 推出的新的大容量骨干路由器,是一个支持多机箱扩展的路由系统.其设计容量可以扩展至72 个线卡机箱.8 个矩阵机箱,总交换容量达到92Tbps,具有 ...

  5. 嵌入式实时程序设计中C/C++代码的优化

    1 引言 计算机技术和信息技术的高速发展的今天,计算机和计算机技术大量应用在人们的日常生活中,嵌入式计算机也得到了广泛的应用.嵌入式计算机是指完成一种或多种特定功能的计算机系统,是软硬件的紧密结合体. ...

  6. ArrayQueue(队列)

    code1: #include <stdio.h> #include <conio.h> #include <stdlib.h> #define MAXSIZE 6 ...

  7. JAVA 常用包

    JAVA是以包的形式进行语言结构组织的. 引入这些包的关键词就是 import 下面说说 JAVA常用包有下面的几个 1. java.lang 这个是默认引入的,也是一个最基础的包.其中lang不是中 ...

  8. IDEA工具java开发之 代码重构Refactor 重命名 删除移动复制 生成变量 抽取方法

    一.重命名 用shift + F6 或者右键单击 二.抽取方法 .三.生成变量 . 四.文件移动复制和删除 可以右键

  9. 神奇的 SQL 之 联表细节 → MySQL JOIN 的执行过程

    问题背景 对于 MySQL 的 JOIN,不知道大家有没有去想过他的执行流程,亦或有没有怀疑过自己的理解(自信满满的自我认为!):如果大家不知道怎么检验,可以试着回答如下的问题 驱动表的选择 MySQ ...

  10. python中的异常处理:厌而不舍

      什么是异常? ------异常:不正常的情况 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行.一般情况下,在Python无法正常处理程序时就会发生一个异常. 异常是Pytho ...