C++快速温习笔记(高级)[3]



文件操作:

数据类型

描述

ofstream

该数据类型表示输出文件流,用于创建文件并向文件写入信息。

ifstream

该数据类型表示输入文件流,用于从文件读取信息。

fstream

该数据类型通常表示文件流,且同时具有 ofstream ifstream 两种功能,这意味着它可以创建文件,向文件写入信息,从文件读取信息。

使用上面的数据类型时,要引用头文件

 

在从文件读取信息或者向文件写入信息之前,必须先打开文件。ofstream fstream 对象都可以用来打开文件进行写操作,如果只需要打开文件进行读操作,则使用 ifstream 对象。

下面是 open() 函数的标准语法,open() 函数是 fstreamifstream ofstream 对象的一个成员。

void open(constchar *filename, ios::openmode mode);

模式标志

描述

ios::app

追加模式。所有写入都追加到文件末尾。

ios::ate

文件打开后定位到文件末尾。

ios::in

打开文件用于读取。

ios::out

打开文件用于写入。

ios::trunc

如果该文件已经存在,其内容将在打开文件之前被截断,即把文件长度设为 0

可以把以上两种或两种以上的模式结合使用,例如:

fstream  afile;

afile.open("file.dat",ios::out | ios::in );

关闭文件:

void close();

 

文件读写示例:

ofstream os;

char* filePath ="d:\\1.txt";

os.open(filePath);

os << "aabbccdd"<< endl;

os.close();

os.open(filePath, ios::app);

os << "eeffgghh"<< endl;

ifstream ist;

ist.open(filePath);

char data[20];

ist >> data;

cout << data;

ist >> data;

cout << data;

 

文件指针位置:

istream ostream 都提供了用于重新定位文件位置指针的成员函数。这些成员函数包括关于 istream seekg"seekget"和关于 ostream seekp"seekput"

seekg seekp 的参数通常是一个长整型。第二个参数可以用于指定查找方向。

查找方向可以是

ios::beg(默认的,从流的开头开始定位)

ios::cur(从流的当前位置开始定位)

ios::end(从流的末尾开始定位,逆向)

文件位置指针是一个整数值,指定了从文件的起始位置到指针所在位置的字节数。

下面是关于定位 "get"文件位置指针的实例:

fileObject.seekg( n );    // 定位到 fileObject 的第 n 个字节(默认是从 ios::beg开始)

fileObject.seekg( n, ios::cur);    // 把文件的读指针从 fileObject 当前位置向后移 n 个字节

fileObject.seekg( n, ios::end);    // 把文件的读指针从 fileObject 末尾往回移 n 个字节

fileObject.seekg( 0, ios::end);    // 定位到 fileObject 的末尾

 

异常处理:

try...catch...语句

try

{

  // 保护代码

}catch( ExceptionName e1 )

{

  // catch

}catch( ExceptionName e2 )

{

  // catch

}catch( ExceptionName eN )

{

  // catch

}catch(...){

  // 如果您想让 catch 块能够处理 try 块抛出的任何类型的异常,则必须在异常声明的括号内使用省略号 ...

}

标准的异常类型(按照继承关系排列):

异常类型(基类)

异常类型(基类)

异常类型(子类)

描述

std::exception

 

 

该异常是所有标准 C++ 异常的父类。

std::exception

std::bad_alloc

 

该异常可以通过 new 抛出。

std::exception

std::bad_cast

 

该异常可以通过 dynamic_cast 抛出。

std::exception

std::bad_exception

 

这在处理 C++ 程序中无法预期的异常时非常有用。

std::exception

std::bad_typeid

 

该异常可以通过 typeid 抛出。

std::exception

std::logic_error

 

理论上可以通过读取代码来检测到的异常。

std::exception

std::logic_error

std::domain_error

当使用了一个无效的数学域时,会抛出该异常。

std::exception

std::logic_error

std::invalid_argument

当使用了无效的参数时,会抛出该异常。

std::exception

std::logic_error

std::length_error

当创建了太长的 std::string 时,会抛出该异常。

std::exception

std::logic_error

std::out_of_range

该异常可以通过方法抛出,例如 std::vector std::bitset<>::operator[]()

std::exception

std::runtime_error

 

理论上不可以通过读取代码来检测到的异常。

std::exception

std::runtime_error

std::overflow_error

当发生数学上溢时,会抛出该异常。

std::exception

std::runtime_error

std::range_error

当尝试存储超出范围的值时,会抛出该异常。

std::exception

std::runtime_error

std::underflow_error

当发生数学下溢时,会抛出该异常。

 

自定义异常举例:

class MyException:public exception{

private:

char msg[100];

public:

MyException(char*m)

{

strcpy(msg, m);

}

const char*what() const throw()

{

return msg;

}

};

try

{

throwMyException("My Demo Exception");

}catch(MyException& e)

{

cout <

}catch(...) { }

 

动态内存:

栈:在函数内部声明的所有变量都将占用栈内存。

堆:这是程序中未使用的内存,在程序运行时可用于动态分配内存。

在程序运行时,可以使用newdelete运算符来动态分配或释放内存。如:

double* pvalue  = NULL; // 初始化为 null 的指针

pvalue  = new double;   // 为变量请求内存

如果自由存储区已被用完,可能无法成功分配内存。所以应检查new 运算符是否返回 NULL 指针,并采取适当的操作:

double* pvalue  = NULL;

if( !(pvalue  = new double ))

{

  cout << "Error: out of memory." <

  exit(1);

}

使用delete释放内存:

delete pvalue;

一维数组的申请与释放:

char* arr = NULL;

arr = new char[20];

delete []arr;

二维数组的申请与释放:

int ROW = 2;

int COL = 3;

double **pvalue  = new double* [ROW];

for(int i = 0; i < COL; i++) {

   pvalue[i] = new double[COL];

}

for(int i = 0; i < COL; i++) {

   delete[] pvalue[i];

}

delete [] pvalue;

对象及对象数组的申请和释放:

class Demo{

public:

Demo() { cout<< "Constructor" << endl; }

~Demo() { cout<< "Deconstructor" << endl; }

};

Demo* demos = new Demo;

delete demos;

demos = new Demo[5];

delete []demos;

 

命名空间:

声明:

namespace namespace_name {

  // 代码声明

}

调用命名空间的资源:

name::code;  // code 可以是变量或函数

使用示例:

namespace namespace1{

void fun1() {cout << "fun1" << endl; }

}

namespace namespace2{

void fun2() {cout << "fun2" << endl; }

}

using namespace namespace1;

fun1();

using namespace2::fun2;

fun2();

不连续的命名空间:

命名空间可以定义在几个不同的部分中,因此命名空间是由几个单独定义的部分组成的。一个命名空间的各个组成部分可以分散在多个文件中。所以,如果命名空间中的某个组成部分需要请求定义在另一个文件中的名称,则仍然需要声明该名称。下面的命名空间定义可以是定义一个新的命名空间,也可以是为已有的命名空间增加新的元素:

namespace namespace_name {

  // 代码声明

}

嵌套命名空间:

namespace namespace_name1 {

  // 代码声明

  namespace namespace_name2 {

      // 代码声明

  }

}

using namespacenamespace_name1::namespace_name2;    // 访问 namespace_name2中的成员

using namespacenamespace_name1;    // 访问 namespace:name1中的成员

你可能感兴趣的:(C++,程序设计,Programming,C++,Programming,程序设计,语法)