C++Primer学习笔记之三

来源:互联网 发布:王师傅c语言 编辑:程序博客网 时间:2024/04/30 07:43

关键字:  函数参数 函数指针  流   流状态  文件

7.8.4 实参类型转换

1 只有当形参是引用或指针时,形参是否为const才有影响。

2 对于即有非const形参又有const形参的重载函数,编译器会根据传递过来的实参类型做出最佳的匹配。

3 合成的默认构造函数,是类默认提供的构造函数,但当含有内置类型变量的类必须提供显示的默认构造函数并给这些变量初始化赋值。

7.9 函数指针

1 函数指针是指向函数的指针,如下声明:

  Bool ( *pf ) ( const string &, const string &)

2 函数指针只能指向与其声明时形参类型完全一致的函数,它不能进行任何形式的形参转换。

3 可使用typedef为指针类型定义同义词,简化函数指针的使用。

typedef  bool (*cmpFcn)(const string &, const string &);

 此定义表示cmpFcn是一种指向函数的指针类型的名字。每次使用它时,直接使用cmpFcn即可。

4 函数指针只能通过同类型的函数或函数指针或0值常量表达式进行初始化或赋值。

5 当函数指针指向一个具体的函数时,可直接使用它来赋值。

6 函数的形参可以是指向函数的指针。存在以下两种形式表达:

 

void useBigger( const string &, const string &, bool ( const string &, const string &) );

void useBigger( const string &, const string &, bool (*) ( const string &, const string &) );

 

7 返回指向函数的指针

int ( *ff(int) ) ( int *, int );

在这里,最外围是一个函数指针形式,内部是一个函数ff(int),由它来返回一个函数指针。

亦可以如下定义:

     typedef  PF int (*) ( int *, int );

PF ff(int);

 

第8章 标准IO库

8.1 面向对象的标准库

  1 IO对象不可复制或赋值,标准库类型不允许做复制或赋值操作。

2 只有支持复制的元素类型可以存储在vector(或其它)容器中(即不存在存储流对象的vector或其它容器)

3 形参或返回类型也不能做为流类型。如果需要传递或返回IO对象,则必须传递或返回指向该对象的指针或引用。

8.2 条件状态

1 IO 标准库管理一系列条件状态成员,用来标记给定的IO对象是否处于可用状态,或者碰到了哪种特定错误。

2 流必须处于无错误状态,才能用于输入或输出。检测流是否可用可使用下面的方法:

      if( cin )

      或

 while( cin>> word )

if语句直接检查流的状态,而while语句则检查条件表达式返回的流,从而间接的检查了流的状态。如果成功输入,则条件检测为true.

3 所有流对象都包含一个iostate类型的条件状态成员,该成员由setstate和clear操作管理。该状态成员以二进制位(bit)形式的形式使用。

4 iostate类型是由各个iostream类分别定义的机器相关的整形。

5 每个IO类还定义了三个iostate类型的常量值,分别表示特定的位模式。这些常量用于指定特定类型的IO条件,可以与位操作符一起使用,以便在一次操作中检查或设置多个标志。

6 badbit标志着系统级的故障,如无法恢复的读写错误。如果出现了错误,此时该流通常不能再继续使用了。

7 对于可恢复的错误,可以使用failbit标志,这时出现错误后可以修正。

8 eofbit是在遇到了文件结束符时设置的,此时还设置了failbit。

9 clear操作将条件重设为有效状态。

10 setstate操作可打开某个指定的条件,用于表示某个问题的发生,同时将保留其他已存在的状态变量不变。

11 流的状态由ban、fail、eof和good操作揭示。如果ban、fail或eof中的 一个为true,则检查流本身将显示该流处于错误状态。如果这三个条件没有一个为true,则good操作将返回true。

12 流状态的查询,流类提供上面所述的各个状态的函数来查询流的状态。下面是对流状态查询的一个例子:

#include <iostream>

using namespace std;

 

void main()

{

  int ival;

 

  while ( cin>>ival, !cin.eof())

  {

       if ( cin.bad())

       {

           throw runtime_error( "IO stream is corrupted" );

 

       }

       if (cin.fail())

       {

           cerr<<" bad data, try again!"<<endl;

           cin.clear(istream::failbit);

           cin.sync();  //在实际的程序运行过程中要加入这一句,cin.sync();要加上这个。这是因

//为clear只是将输入流状态设置为有效了,但是缓冲区内的数据还在,会读入//又使其无效,所以就在有效无效之间循环下去了, 比如你输入'A'破坏了输//入流,你用clear将输入流设置为有效 //但是A还在缓冲区,又会被读入破坏//输入流,sync()能够清空数据流,使A消失,重新读数。缓冲区有数据的话,//它就会一直读缓冲区的数据,直到碰到结束标记,但是这个缓冲区一直没刷//新,所以就陷入了死循环中。

           continue;

       }

       cout<<" ival = "<<ival<<endl;

  }

}

13 条件状态的访问

可以使用rdstate成员函数返回的iostate类型的值来保存流当前的整个条件状态。

  istream::iostate old_state = cin.rdstate();

cin.clear();

process_input();

 

cin.clear(old_state);

 

14 由于流的各个状态是通过标志位控制的,可以使用与二进制操作的方法同时设置几个状态。

8.3 输出缓冲区的管理

1下面几种情况将导致缓冲区的内容被刷新,即将写入到真实的输出设备或者文件:

  (1)程序正常结束时,作为main返回工作的一部分,将清空所有输出缓冲区。

  (2)在缓冲区满时,再向缓冲区写入下一个数据之前会刷新。

  (3)用操纵符显式地刷新缓冲区,如行结束符endl;

  (4)在每次输出操作执行完后,用unitbuf操作符设置流的内部状态,从而清空缓冲区。

  (5)可将输出流与输入流关联起来。这时,在读输入流时将刷新其关联的输出缓冲区。

 

2 输出缓冲区的刷新

endl:输出一个换行符并刷新缓冲区

flush:刷新流,但在输出中不添加任何字符。

ends:在缓冲区中插入空字符,然后刷新它。

3 unitbuf可刷新所有输出。与nounitbuf一起使用。

cout<< unitbuf << “first” << “ second “ << nounitbuf;

等价于:

 cout << “first” << flush <<  “ second “ <<  flues;

 

nounitbuf将流恢复为使用正常的、由系统管理的缓冲区刷新方式。

 

4 使用tie()函数将输入与输出绑在一起:

  cin.tie(&cout); 绑定

  cin.tie(0);  解绑

8.4 文件的输出与输入

8.4.1 文件流对象的使用

 1 在一个循环中应尽量不要创建一个局部文件对象,而是应尽量把文件对象的创建放在循环外,这样可以避免每次循环过程中创建新的流对象,在循环结束时要对文件流的状态重新恢复,避免将错误的状态一直保持下去,影响后面的读写。

假设一个vector容器对象files中存放的是文件名。

{

    ifstream input;

    vector< string >::const_iterator it = files.begin();

    while( it != files.end() )

    {

        input.open( it->c_str() );  //open the file;

       //if the file is ok, read and "process" the input

       if ( !input )

       {

           process(s);

       }

       input.close();  //close file when we're donw with it

       input.clear();   //reset state to ok

       ++it;             //increment iterator to get netxt file

    }

};

 

原创粉丝点击