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. 【代码总结】PHP面向对象之接口与多态性应用

    概述: PHP之支持单继承,也就是说每个类智能继承一个父类.当声明的新类继承抽象类实现模板以后就不能再有其他问题,为了解决这个问题,PHP引用了接口 ------------------------- ...

  2. Golang redis 学习指南

    安装 我使用的是 https://github.com/go-redis/r... 这个 golang 客户端, 因此安装方式如下: go get gopkg.in/redis.v4 接着在代码中导入 ...

  3. ETCD监控

    Watch key changes Applications can watch on a key or a range of keys to monitor for any updates. Her ...

  4. 吴裕雄 python 神经网络——TensorFlow pb文件保存方法

    import tensorflow as tf from tensorflow.python.framework import graph_util v1 = tf.Variable(tf.const ...

  5. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 网格系统实例:手机、平板电脑、台式电脑

    <!DOCTYPE html> <html> <head> <title>Bootstrap 实例 - 手机.平板电脑.台式电脑</title&g ...

  6. 学习笔记(5)- ubuntu对话语料

    The Ubuntu Dialogue Corpus: A Large Dataset for Research in Unstructured Multi-Turn Dialogue Systems ...

  7. 时隔两天,三星再称GalaxyFold已准备就绪,王自如的脸还好吗?

    编辑 | 禾斗 出品 | 于见(mpyujian) 据消息人士透露,三星已经完成对其有缺陷的折叠智能手机进行了重新设计,Galaxy Fold准备适时再度推出,但问题是,作为消费者,我们准备好了吗? ...

  8. 夯实Java基础系列目录

    自进入大学以来,学习的编程语言从最初的C语言.C++,到后来的Java,. NET.而在学习编程语言的同时也逐渐决定了以后自己要学习的是哪一门语言(Java).到现在为止,学习Java语言也有很长一段 ...

  9. android悬浮按钮(Floating action button)的两种实现方法

    原文: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1028/1857.html 最近android中有很多新的设计规范被引入 ...

  10. PAT A 1020 Tree Traversals

    给出一棵二叉树的后序遍历序列和中序遍历序列,求这棵二叉树的层序遍历序列 #include<iostream> #include<cstring> #include<que ...