CH8 IO库
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库的更多相关文章
- [APUE]标准IO库(下)
一.标准IO的效率 对比以下四个程序的用户CPU.系统CPU与时钟时间对比 程序1:系统IO 程序2:标准IO getc版本 程序3:标准IO fgets版本 结果: [注:该表截取自APUE,上表中 ...
- [APUE]标准IO库(上)
一.流和FILE对象 系统IO都是针对文件描述符,当打开一个文件时,即返回一个文件描述符,然后用该文件描述符来进行下面的操作,而对于标准IO库,它们的操作则是围绕流(stream)进行的. 当打开一个 ...
- 文件IO函数和标准IO库的区别
摘自 http://blog.chinaunix.net/uid-26565142-id-3051729.html 1,文件IO函数,在Unix中,有如下5个:open,read,write,lsee ...
- 【转载】C++ IO库
本篇随笔为转载,原贴地址:<C++ Primer>第8章 IO库 学习笔记. 1.IO类 #include <iostream> istream//从流中读取数据 ostrea ...
- 从Decorator,Adapter模式看Java的IO库
我想任何一本介绍模式的书在讲到Decorator模式的时候不能不提到它的实际应用--在Java/IO库里面的应用,<<Java与模式>>这本书也不例外,有点不一样的是,这本书在 ...
- C++ Primer 读书笔记: 第8章 标准IO库
第8章 标准IO库 8.1 面向对象的标准库 1. IO类型在三个独立的头文件中定义:iostream定义读写控制窗口的类型,fstream定义读写已命名文件的类型,而sstream所定义的类型则用于 ...
- 标准模板库——IO库
IO库设施: . istream(输入流)类型,提供输入操作. . ostream(输出流)类型,提供输出操作. . cin,一个istream对象,从标准输入读取数据. . cout,一个ostre ...
- 高级UNIX环境编程5 标准IO库
标准IO库都围绕流进进行的 <stdio.h><wchar.h> memccpy 一般用汇编写的 ftell/fseek/ftello/fseeko/fgetpos/fsetp ...
- IO库
IO类 C++语言不直接处理出入输出,而是通过一族定义在标准库中的类型来处理IO.这些类型支持从设备读取数据.向设备写入数据的IO操作,设备可以是文件 .控制台窗口 等.还有一些类型允许内存IO ,即 ...
随机推荐
- 「题解」「JOISC 2014 Day1」历史研究
目录 题目 考场思考 思路分析及标程 题目 点这里 考场思考 大概是标准的莫队吧,离散之后来一个线段树加莫队就可以了. 时间复杂度 \(\mathcal O(n\sqrt n\log n)\) . 然 ...
- 一个高级PHP工程师所应该具备的(转自元如枫博客)
初次接触PHP,就为他的美所折服,于是一发不可收拾. 很多面试,很多人员能力要求都有“PHP高级工程师的字眼”,如果您真心喜欢PHP,并且您刚起步,那么我简单说说一个PHP高级工程师所应该具备的,希望 ...
- stm32CubeMx lwip + freeRTOS
MCU: STM32F429IGT6 工具:STM32CubeMx 版本号 5.0.0 Keil uVersion5 目的:使用LWIP 实现简单的网络连通 一 简介 LWIP(Light Wei ...
- C++98常用特性介绍——mutable关键字
讲mutable前,先讲一下const函数,讲const函数前,先讲一下函数前后加const的区别 一.C++函数前后加const的区别 1)函数前加const:普通函数或非静态成员函数前均可加con ...
- 第一节:Vuejs入门之各种指令
一. 简介 Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层,不仅易于上 ...
- vue中加载three.js的gltf模型
vue中加载three.js的gltf模型 一.开始引入three.js相关插件.首先利用淘宝镜像,操作命令为: cnpm install three //npm install three也行 二. ...
- php 基础知识 post 和get 两种传输方式的区别
1.post更安全(不会作为url的一部分,不会被缓存.保存在服务器日志.以及浏览器浏览记录中) 2.post发送的数据量更大(get有url长度限制) 3.post能发送更多的数据类型(get只能发 ...
- 50道SQL练习题及答案与详细分析(MySQL)
50道SQL练习题及答案与详细分析(MySQL) 网上的经典50到SQL题,经过一阵子的半抄带做,基于个人理解使用MySQL重新完成一遍,感觉个人比较喜欢用join,联合查询较少 希望与大家一起学习研 ...
- java8函数式编程实例
什么是函数式编程 函数式编程是java8的一大特色,也就是将函数作为一个参数传递给指定方法.别人传的要么是基本数据类型,要么就是地址引用 ,我们要穿一个“动作”. Stream 说到函数式编程,就不得 ...
- Python数据类型-1 数据类型介绍
数据类型 在python这门语言中,数据类型分为两种. 内置的和自定义的. 内置的包括数字.字符串.布尔.列表.元组.字典.Bytes.集合这些常用的以及一些不太常用的数据类型.而自定义的,一般以类的 ...