C++11 Primer Plus(五)之类与标准模板和文件

自己写的C++11 Primer Plus 学习笔记,如有雷同不胜荣幸,如有错误敬请指正


1. 友元,异常和其他

1. 嵌套类: 在另一个类中声明的类

嵌套类,结构和枚举的作用域特征

声明位置 包含它的类是否可以使用它 从包含它的类派生而来的类是否可以使用它 在外部是否可以使用
私有部分
保护部分
公有部分 是,通过类限定符来使用

2. 异常

abort() 的典型实现是向标准错误流(即:cerr 使用的错误流)发送消息 abnormal program termination(程序异常终止),然后终止程序(是否刷新问价缓冲区取决于实现)。exit() 刷新文件缓冲区,但不显示消息。

异常处理的三个组成部分:

  • 引发异常
  • 使用处理程序捕获异常
  • 使用 try 块

**异常规范(C++11已摒弃,推荐:关键字 noexcept 指出函数不会引发异常)

double harm(double a) throw(bad_thing); //may throw bad_thing exception
double marm(double) throw();            //doesn't throw an exception

///////////////////////
double marm() noexcept;     //marm() doesn't throw an exception

其中的 throw() 就是异常规范,它可能出现在函数原型和函数定义中,可包含类型列表,也可不包含
异常规范作用:

  • 告诉用户可能需要使用try 块,当然也可以在注释中指出
  • 让编译器添加执行运行阶段检查的代码,检查是否违反了异常规范

栈解退: 当函数由于异常(不是由于返回)而终止,则程序也将释放栈中的内存,但不会释放栈的第一个返回地址后停止,而是继续释放栈,直到找到一个位于 try 块中的返回地址。随后,控制权将转到块尾的异常处理程序,而不是函数调用后面的第一条语句。(如果栈解退,则引发异常后,对于中间函数调用放在栈中的自动类型对象,其析构函数将不会被调用)

引发异常时,编译器总是创建一个临时拷贝,即使异常规范和 catch 块中指定的是引用

引用作为返回值的原因: 基类引用可以执行派生类对象。假设有一组通过继承关联起来的异常类型,则在异常规范中只需列出一个基类引用,它将与任何派生类对象匹配。
假设有一个异常类层次结构,并要分别处理不同异常类型,则使用基类引用将能够捕获任何异常对象;而使用派生类对象只能捕获它所属类及从这个类派生而来的类对象。

可以使用省略号来表示异常类型,从而捕获异常:

catch(...){ //statements }; //catches any type exception  

重新定义:

#include
class bad_hmean : public std::exception
{
public:
    const char * what(){return "bad arguments to hmean()";}
    ...
};

class bad_gmean : public std::exception
{
public:
    const char * what(){return "bad arguments to gmean()";}
    ...
};


try{
...
}catch(std::exception & e)
{
    cout << e.what() << endl;
    ...
}

存在浮点类型可以表示的最小非零值,计算结果比这个值还小时将导致下溢错误;整形和浮点型都可能发生上溢错误,当计算结果超过了某个类型能够表示的最大数量级时,将发生上溢错误。

要捕获所有异常(预期和意外异常):

  • 首先确保异常头文件的声明可用:

    #include
    using namespace std;
  • 然后,设计一个替代函数,将意外异常转换为 bad_exception 异常,该函数原型如下:

    void myUnexpected()
    {
    throw std::bad_exception; //or just throw
    }

    仅使用 throw ,而不是指定异常将导致重新引发原来的异常。然而,如果异常规范中包含了这种类型,则该异常将被 bad_exception 对象所取代
  • 接下来在程序开始位置,将意外异常操作指定为调用该函数:set_unexcepted(myUnexpected);
  • 最后,将 bad_exception 类型包含在异常规范中,并添加如下 catch 块序列:

    double Argh(double,double) throw (out_of_bounds,bad_exception);
    ...
    try{
    x = Argh(a,b);
    }catch(out_of_bounds & ex)
    {
    ...
    }catch(bad_exception & ex)
    {
    ...
    }

3. RTTI(运行阶段类型识别:Runtime Type Identification): 旨在为程序在运行阶段确定对象的类型提供一种标准方式。

C++ 支持 RTTI 的元素:

  • 如果可能的话,dynamic_cast 运算符将使用一个指向基类的指针来生成一个指向派生类指针;否则,该运算符返回0——空指针
  • typeid 运算符返回一个指出对象的类型的值
  • type_info 结构存储了有关特定类型的信息

dynamic_cast运算符: Superb * pm = dynamic_cast(pg);
typeid 运算符和 type_info 类:

  • typeid 运算符使得能够确定两个对象是否为同种类型,可接受两个参数:① 类名 ② 结果为对象的表达式 。typeid 运算符返回一个对 type_info 对象的引用,例如:如果 pg 指向的是一个 Mag 对象,则下述表达式的结果为true,否则为false:typeid(Mag) == typeid(*pg)
  • type_info 类的实现随厂商而异,但包含一个 name() 成员,该函数返回一个随实现而异的字符串:通常是类的名称

4. 类型转换运算符

  • dynamic_cast
  • const_cast
  • static_cast
  • reinterpret_cast

dynamic_cast: dynamic_cast(expression),该运算符的作用是使得能够在类层次结构中进行向上转换,而不允许其他转换
const_cast: const_cast (expression),该运算符的作用是改变值为 constvolatile
(type-name 与 expression 的类型必须相同)

High bar;
const High * pbar = &bar;
...
High * pb = const_cast (pbar);  //valid
const Low * pl = const_cast<const Low *> (pbar);    //invalid

static_cast: static_cast (expression),仅当 type_name 可被隐式转换为 expression 所属的类型或 expression 可被隐式转换为 type_name 所属的类型时,上述转换才是合法的。

High bar;
Low blow;
...
High * pb = static_cast (&blow);    //valid upcast
Low * pl = static_cast (&bar);       //valid downcast
Pond * pmer = static_cast (&blow);  //invalid,Pond unrelated

reinterpret_cast: reinterpret_cast (expression),用于天生危险的类型转换

struct dat {short a; short b;};
long value = 0xA224B118;
dat * pd = reinterpret_cast (&value);
cout << hex << pd->a;   //display first 2 bytes of value

通常,这样的转换适用于依赖实现的底层编程技术,是不可移植的。例如:不同系统在存储多字节整形时,可能以不同的顺序存储其中的字节。


2. string 类和标准模板库

1. string 类

string 类的构造函数

(string 实际上是模板具体化 basic_string 的一个 `typedef)

构造函数 描述
string(const cahr * s) 将 string 对象初始化为 s 指向的 NBTS
string(size_type n,cahr c) 创建一个包含 n 个元素的 string 对象,其中每个元素都被初始化为字符 c
string(const string & str) 将一个 string 对象初始化为 string 对象 str (复制构造函数)
string() 创建一个默认的string对象,长度为0(默认构造函数)
string(const char * s,size_type n) 将 string 对象初始化为 s 指向的 NBTS 的前 n 个字符,即使超过了 NBTS 结尾
template< class Iter> string(Iter begin,Iter end) 将 string 对象初始化为区间[begin,end)内的字符,其中begin和end行为就像指针,用于指定位置,范围包括begin在内,但不包括end
string(const string & str,string size_type pos=0,size_type n=npos) 将一个string 对象初始化为对象 str 中从位置 pos 开始到结尾的字符,或从位置 pos 开始的 n 个字符
string(string && str) noexcept 它将一个string对象初始化为string对象str,并可能修改str(移动构造函数)
string(initializer_list il) 它将一个string对象初始化为初始化列表il中的字符

**string 版本的 getline() 函数从输入中读取字符,并将其储存到目标string中,直到发生下列三种情况之一:

  • 到达文件尾,在这种情况下,输入流的 eofbit 将被设置,这意味着方法 fail()eof() 都将返回 true;
  • 遇到分界字符(默认为\n),在这种情况下,将把分界字符从输入流中删除,但不储存它
  • 读取的字符数达到最大允许值(string::npos(通常是无符号 int 或 无符号 long 的最大值) 和可供分配的内存字节数中较小的一个),在这种情况下,将设置输入流的 failbit,这意味着方法 fail()将返回 true

重载的 find() 方法

方法原型 描述
size_type find(const string & str,size_type pos=0) const 从字符串的 pos 位置开始,查找子字符串 str。如果找到,则返回该子字符串首次出现时其首字符的索引;否则,返回 string::npos
size_type find(const char * s,size_type pos=0)const 从字符串的 pos 位置开始,查找子字符串 s。如果找到,则返回该子字符串首次出现时其首字符的索引;否则,返回 string::npos
size_type find(const char * s,size_type pos=0,size_type n) 从字符串的 pos 位置开始,查找 s 的前 n 个字符组成的子字符串。如果找到,则返回该子字符串首次出现时其首字符的索引;否则,返回 string::npos
size_type find(char ch,size_type pos=0)const 从字符串的 pos 位置开始,查找字符 ch。如果找到,则返回该字符首次出现的位置;否则,返回 string::npos

string 库还提供了相关方法:rfind(),find_last_of(),find_first_of(),find_first_not_of(),find_last_not_of(),它们重载函数特征标都与 find() 方法相同。rfind() 方法查找子字符串或字符最后一次出现的位置;find_first_of() 方法在字符串中查找参数中任何一个字符首次出现的位置;find_last_of() 查找最后一次出现的位置;find_first_not_of() 在字符串中查找第一个不包含在参数中的字符

2. 智能指针模板类(智能指针是行为类似于指针的模板类对象)

  • auto_ptr
  • unique_ptr
  • shared_ptr

普通指针过期时,其所占据的内存将被释放,但其所指向的内存将不会被释放(因为其不是对象,无法调用其析构函数来删除其指向的内存)

这三个智能指针模板都定义了类似指针的对象,可以将 new 获得的地址赋给这种对象,其析构函数将使用 delete 来释放内存。因此,如果将 new 返回的地址赋给这些对象,将无需记住稍后释放这些内存:在智能指针过期时,这些内存将自动释放

避免程序删除一个对象两次:

  • 定义赋值运算符,使之执行深复制。这样两个指针将指向不同的对象,其中的一个对象是另一个对象的副本
  • 建立所有权概念,对于特定的对象,只能有一个只能指针可拥有它,这样只有拥有对象的智能指针的构造函数会删除该对象。然后,让赋值操作转让所有权。这就是 auto_ptrunique_ptr 的策略,但 unique_ptr 的策略更严格
  • 创建智能更高的指针,跟踪引用特定对象的指针数,称为引用计数。例如:赋值时,计数将加1,而指针过期时,计数将减1,仅当最后一个指针过期时,才调用 delete。这是 shared_ptr 采用的策略。

unique_ptr 优于 auto_ptr

auto_ptr<string> p1 = new string("auto");   //#1
auto_ptr<string> p2;                        //#2
p2 = p1;                                    //#3

在语句 #3 中,p2 接管 string 对象的所有权后,p1 的所有权将被剥夺。这样可防止 p1 和 p2 的析构函数试图删除同一个对象;但如果程序随后试图使用 p1,这将是坏事,因为p1 不再指向有效的数据。

unique_ptr<string> p3 = new string("auto"); //#4
unique_ptr<string> p4;                      //#5
p4 = p3;                                    //#6;

编译器认为语句 #6 非法,避免了 p3 不再指向有效的数据的问题。
程序试图将一个 unique_ptr 赋给另一个时,如果源 unique_ptr 是一个临时右值,编译器允许这样做;如果源 unique_ptr 将存在一段时间,编译器将禁止这样做:

unique_ptr<string> pu1 = new string("hi");
unique_ptr<string> pu2;
pu2 = pu1;                                      //#1 not allowed
unique_ptr<string> pu3;
pu3 = unique_ptr<string>(new string("you"));    //#2 allowed

同时,unique_ptr 还可用于数组的变体

使用 new 分配内存时,才能使用 auto_ptrshared_ptr;不使用 new 或 new[] 分配内存时,不能使用 unique_ptr

3. 标准模板库

① 模板类 vector

templateT,class Allocator = allocator<T>>
    calss vector{...

如果省略该模板参数的值,则容器模板将默认使用 allocator 类(这个类使用 new 和 delete)
vector 模板使用动态内存分配,因此可以初始化参数来指出需要多少矢量

STL 容器的基本方法:

  • size():返回容器中元素的数目
  • swap():交换两个容器的内容
  • begin():返回一个指向容器中第一个元素的迭代器
  • end():返回一个表示超过容器尾的迭代器
  • erase():删除矢量中给定区间的元素

4. 泛型编程

面向对象编程关注的是编程的数据方面,而泛型编程关注的是算法。它们之间的共同点是抽象和创建可重用代码。泛型编程旨在编写独立于数据类的代码。

迭代器类型:

  • 输入迭代器:可被程序用来读取容器中的信息。具体的说,对输入迭代器解除引用将使程序能够读取容器中的值,但不一定能让程序修改值。基于输入迭代器的任何算法都应当是单通行的,不依赖于前一次遍历时的迭代器值,也不依赖于本次遍历中前面的迭代器值
  • 输出迭代器:指用于将信息从程序传输给容器的迭代器,解除引用让程序能修改容器值,而不能读取
  • 正向迭代器:正向迭代器只使用 ++ 运算符来遍历容器;既可以使得能够读取和修改数据,也可以使得只能读取数据
  • 双向迭代器:双向迭代器具有正向迭代器的所有特性,同时支持递减运算符
  • 随机访问迭代器 :随机访问迭代器具有双向迭代器的所有特性,同时添加了支持随机访问的操作(如指针增加运算)和用于对于元素进行排序的关系运算符

迭代器性能

迭代器功能 输入 输出 正向 双向 随机访问
解除引用读取
解除引用写入
固定和可重复排序
++i,i++
–i i–
i[n]
i + n
i - n
i += n
i -= n

一些基本的容器特征

从快到慢依次为编译时间,固定时间,线性时间

表达式 返回类型 满足正向迭代器要求的任何迭代器 编译时间
X::iterator 指向 T 的迭代类型 满足正向迭代器要求的任何迭代器 编译时间
X::value_type T T 的类型 编译时间
X u; 创建一个名为u的空容器 固定
X() 创建一个匿名的空容器 固定
X u(a); 调用复制构造函数后u == a 线性
X u = a; 作用同 X u(a) 线性
r = a; X& 调用赋值运算符后r == a 线性
(&a)->~X() void 对容器中的每个元素应用析构函数 线性
a.begin() 迭代器 返回指向容器第一个元素的迭代器 固定
a.end() 迭代器 返回超尾值迭代器 固定
a.size() 无符号整形 返回元素个数,等价于a.end()-a.begin() 固定
a.swap(b) void 交换 a 和 b 的内容 固定
a == b 可转换为 bool 如果a和b的长度相同,且a中每个元素都等于(==为真)b中相应的元素,则为真 线性
a != b 可转换为bool 返回 !(a==b) 线性
X u(rv) 调用移动构造函数后,u 的值与 rv 的原始值相同 线性
X u = rv; 作用同 X u(rv)
a = rv; X & 调用移动赋值运算符后,u的值与rv的原始值相同 线性
a.cbegin() const_iterator 返回指向容器第一个元素的 const 迭代器 固定
a.cend() const_iterator 返回超尾值 const 迭代器 固定

7种序列容器类型:

  • vector:vector是数组的一种表示,它提供了自动内存管理功能,可以动态的改变vector对象的长度,并随着元素的添加和删除而增大和缩小。它提供了对元素的随机访问。在尾部添加和删除元素的时间是固定的,但在头部或中间插入和删除元素的复杂度为线性时间。它还是一个反转容器
  • deque:表示双端队列,类似于vector,区别是从deque对象的开始位置插入和删除元素的时间是固定的
  • list:表示双向链表,除了第一个和最后一个元素外,每个元素都与前后的元素相链接,这意味着可以双向遍历链表,与vector的区别是list在链表中任一位置进行插入和删除的时间都是固定的。因此,vector强调的是通过随机访问进行快速访问,而
    list 强调的是元素的快速插入和删除
  • forward:实现了但链表,在这个链表中,每个节点只链接到下一个节点而没有链接到前一个节点
  • queue:是一个适配器类
  • priority_queue:也是一个适配器类,与queue的区别是在 priority_queue 中,最大的元素被移到队首;外部区别是默认的底层类是vector
  • stack:也是一个适配器类,它给底层类提供了典型的栈接口
  • array:

关联容器(将值与键关联在一起,并使用键来查找值): set,multiset,map,multimap

优点:提供了对元素的快速访问;关联容器通常用于确定数据放置位置的算法,以便能够快速检索信息。

  • set:其值类型与键相同,键是唯一的
  • multiset:类似于set,只是可能有多个值的键相同
  • map:值与键的类型不同,键是唯一的,每个键只对应一个值
  • multimap:类似于map,只是可以与多个值相关联

无序关联容器: 也是将值与键关联起来,并使用键来查找值;底层差别在于,关联容器是基于数结构的,而无序关联容器是基于数据结构哈希表的,这旨在提高添加和删除元素的速度以及提高查找算法的效率(unordered_set,unordered_multiset,unordered_map,unordered_multimap)

5. 函数对象(函数符): 是可以以函数方式与 () 结合使用的任意对象,这包括函数名,指向函数的指针,重载了 () 运算符的类对象

函数符概念:

  • 生成器是不用参数就可以调用的函数符
  • 一元函数是一个参数可以调用的函数符
  • 二元函数是用两个参数可以调用的函数符
  • 返回 bool 值的一元函数是谓词
  • 返回 bool 值的二元函数是二元谓词

运算符和相应的函数符

运算符 相应的函数符
+ plus
- minus
* multiplies
/ divides
% modules
- negate
== equal_to
!= not_equal_to
> greater
< less
>= greater_equal
<= less_equal
&& logical_and
|| logical_or
! logical_not

使函数成为自适应的原因是,它携带了标识参数类型和返回类型的 typedef 成员,这些成员分别是 result_type,first_argument_type,second_argument_type。
函数符自适应的意义是:函数适配器对象可以使用函数对象,并认为存在这些 typedef 成员

6. 算法

STL 将算法库分成:

  • 非修改式序列操作:对区间中的每个元素进行操作,这些操作不修改容器的内容
  • 修改式序列操作:对区间的每个元素进行操作,可以修改容易的内容;可以修改值,也可以修改值的排列顺序
  • 排序和相关操作:包括多个排序函数和其他各种函数,包括集合操作
  • 通用数字运算:包括将区间的内容积累,计算两个容器的内部乘积,计算小计,计算相邻对象差的函数

3. 输入,输出和文件

1. C++输入输出概述

输出时,程序首先填满缓冲区,然后把整块数据传输给硬盘,并清空缓冲区,已被下一批输出使用,这被成为刷新缓冲区(C++在用户按下回车键时刷新缓冲区)

  • streambuf 类为缓冲区提供了内存,并提供了用于填充缓冲区,访问缓冲区内容,刷新缓冲区和管理缓冲区内存的类方法
  • ios_base类表示流的一般特征,如是否可读取,是二进制流还是文本流等(存储了描述格式状态的信息,通过使用 ios_base 的成员函数,可以控制字段宽度和小数位数)
  • ios 类基于 ios_base,其中包括了一个指向 streambuf 对象的指针成员
  • ostream 类是从 ios 类派生而来的,提供了输出方法(ostream 类最重要的任务之一是将数值类型转换为以文本形式表示的字符值,ostream 将数据内部表示转换为由字符字节组成的输出流。由于ostream 类对于 cout 对象处理的输出流进行缓冲,所有输出不会立即发送到目标地址,而是被存储在缓冲区中,知道缓冲区填满。然后程序将刷新缓冲区,把内容发送出去,并清空缓冲区,以存储新的数据)
  • istream 类也是从 ios 类派生而来的,提供了输入方法
  • iostream 类是基于 istream 和 ostream 类的,因此继承了输入和输出方法

在程序中包含 iostream 文件将自动创建 8 个流对象(4 个用于窄字符流,4 个用于宽字符流):

  • cin(wcin) 对象对应于标准输入流
  • cout(wcout) 对象对应于标准输出流
  • cerr(wcerr) 对象与标准错误流对应,可用于显示错误消息。这个流不会被缓冲,这意味着信息将直接被发送到屏幕
  • clog(wclog) 对象也对应标准错误流,这个流被缓冲

setf()的格式常量

常量 含义
ios_base::boolalpha 输入和输出 bool 值,可以为 true 或 false
ios_base::showbase 对于输出,使用C++基数前缀(0,0x)
ios_base::showpoint 显示末尾的小数点
ios_base::uppercase 对于16进制输出,使用大写字母,E表示法
ios_base::showpos 在正数前面加上 +

setf(long,long)的参数

第二个参数 第一个参数 含义
ios_base::basefield ios_base::dec 使用基数 10
ios_base::oct 使用基数8
ios_base::hex 使用基数16
ios_base::floatfield ios_base::fixed 使用定点计数法
ios_base::scientific 使用科学计数法
ios_base::adjustfield ios_base::left 使用左对齐
ios_base::right 使用右对齐
ios_base::internal 符号或基数前缀左对齐,值右对齐

一些标准控制符

控制符 调用
boolalpha setf(ios_base::boolalpha)
noboolalpha unsetf(ios_base::noboolalpha)
showbase setf(ios_base::showbase)
noshowbase unsetf(ios_base::noshowbase)
showpoint setf(ios_base::showpoint)
noshowpoint unsetf(ios_base::noshowpoint)
showpos setf(ios_base::showpos)
uppercase setf(ios_base::uppercase)
internal setf(ios_base::internal,ios_base::adjustfield)
left setf(ios_base::left,ios_base::adjustfield)
right setf(ios_base::right,ios_base::adjustfield)
dec setf(ios_base::dec,ios_base::adjustfield)
hex setf(ios_base::hex,ios_base::adjustfield)
oct setf(ios_base::oct,ios_base::adjustfield)
fixed setf(ios_base::fixed,ios_base::adjustfield)
scientific setf(ios_base::scientific,ios_base::adjustfield)

**头文件 iomanip 最常用的控制符分别是 setprecision(),setfill(),setw(),它们分别用来设置精度,填充字符和字段宽度。setprecision() 控制符接受一个指定精度的正数参数,setfill() 控制符接受一个指定填充字符的 char 参数,setw() 控制符接受一个制定字符==字段宽度的正数参数

流状态: 由三个 ios_base 元素组成(eofbit,badbit,failbit),其中每个元素都是一位,可以是1(设置)或0(清除)。当 cin 操作到达文件末尾时,它将设置 eofbit;当 cin 操作未能读取到预期的字符时,它将设置 failbit(I/O失败也可能将 failbit 设置为 1);在一些无法诊断的失败破坏流时,badbit 元素将被设置。当全部三个状态位都设置为 0 时,说明一切顺利;程序可以检查流状态,并使用这种信息来决定下一步做什么

流状态

成员 描述
eofbit 如果到达文件尾,则设置为1
badbit 如果流被破坏,则设置为1
failbit 如果输入操作未能读取预期的字符或输出操作没有写入预期的字符,则设置为1
goodbit 另一种表示 0 的方法
good() 如果流可以使用(所有位都被清除),则返回true
eof() 如果 eofbit 被设置,则返回 true
bad() 如果 badbit 被设置,则返回true
fail() 如果 badbit或failbit 被设置,则返回true
rdstate() 返回流状态
exceptions() 返回一个位掩码,指出哪些标记导致异常被引发
exceptions(isostate ex) 设置哪些状态将导致clear()引发异常
clear(iostate s) 将流状态设置为 s ;s 的默认值为0(goodbit);如果(restate()&exceptions())!=0,则引发异常 basic_ios::failure
setstate(iostate s) 调用 clear(rdstate()|s)。这将设置与s中设置的位对应的流状态位,其他流状态位保持不变

clear()setstate() 都重置状态,但 clear() 将状态设置为它是参数,而setstate() 方法只是影响其参数中已设置的位)

exceptions() 方法返回一个位字段,它包含三位,分别对应 eofbit,badbit,failbit。修改流状态涉及 clear(),setstate(),这都将使用 clear()。修改流状态后,clear()方法将当前的流状态与exceptions() 返回的值进行比较。如果在返回值中某一位被设置,而当前状态中的对应位也被设置,则 clear() 将引发 ios_base::failure 异常。

cin.get(ch)与cin.get()

特征 cin.get(ch) cin.get()
传输输入字符的方法 赋给参数ch 将函数返回值赋给ch
字符输入时函数的返回值 指向 istream 对象的引用 字符编码(int 值)
达到文件尾时函数的返回值 转换为 false EOF

输入行为

方法 行为
getline(char *,int) 如果没有读取任何字符(但换行符被视为读取了一个字符),则设置 failbit;如果读取了最大数目的字符,且行中还有其他字符,则设置 failbit
get(char *,int) 如果没有读取任何字符,则设置 failbit

peek() 函数返回输入中的下一个字符,但不抽取输入流中的字符
gcount() 方法返回最后一个非格式化抽取方法读取的字符数
putback() 函数将一个字符插入到输入字符中,被插入的字符将是下一条输入语句读取的第一个字符|

2. 文件输入和输出

以默认模式打开文件进行输入将自动把文件的长度截断为零,这相当于清除已有的内容。

读取文件的要求与写入文件相识:

  • 创建一个与 ifstream 对象来管理输入流
  • 将该对象与特定的文件关联起来
  • 以使用 cin 的方式使用该对象

文件模式常量

常量 含义
ios_base::in 打开文件,以便读取
ios_base::out 打开文件,以便写入
ios_base::ate 打开文件,并移到文件尾
ios_base::app 追加到文件尾
ios_base::trunc 如果文件存在,则截短文件
ios_base::binary 二进制文件

C++和C的文件打开模式

C++模式 C模式 含义
ios_base::in “r” 打开以读取
ios_base::out “w” 等价于 ios_base::out | ios_base::trunc
ios_base::out | ios_base::trunc “w” 打开以写入,如果已经存在,则截短文件
ios_base::out | ios_base::app “a” 打开以写入,只追加
ios_base::out | ios_base::out “r+” 打开以读写,在文件允许的位置写入
ios_base::out | ios_base::out | ios_base::trunc “w+” 打开以读写,如果已经存在,则首先截短文件
c++mode | ios_base::binary “cmodeb” 以 C++mode(或相应的cmode)和二进制模式打开;例如:ios_base::in | ios_base::binary 成为 “rb”
c++mode | ios_base::ate “cmode” 以指定的模式打开,并移到文件尾。C 使用一个独立的函数调用,而不是模式编码

3. 内核格式化: 读取 string 对象中的格式化信息或将格式化信息写入 string 对象中。

  • iostream 族支持程序与终端之间的 I/O
  • fstream 族使用相同的接口提供程序和文件之间的 I/O
  • sstream 族 使用相同的接口提供程序和string 对象之间的 I/O

你可能感兴趣的:(C/C++篇)