文件操作:
数据类型 |
描述 |
ofstream |
该数据类型表示输出文件流,用于创建文件并向文件写入信息。 |
ifstream |
该数据类型表示输入文件流,用于从文件读取信息。 |
fstream |
该数据类型通常表示文件流,且同时具有 ofstream 和 ifstream 两种功能,这意味着它可以创建文件,向文件写入信息,从文件读取信息。 |
使用上面的数据类型时,要引用
在从文件读取信息或者向文件写入信息之前,必须先打开文件。ofstream 和 fstream 对象都可以用来打开文件进行写操作,如果只需要打开文件进行读操作,则使用 ifstream 对象。
下面是 open() 函数的标准语法,open() 函数是 fstream、ifstream 和 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(...) { }
动态内存:
栈:在函数内部声明的所有变量都将占用栈内存。
堆:这是程序中未使用的内存,在程序运行时可用于动态分配内存。
在程序运行时,可以使用new和delete运算符来动态分配或释放内存。如:
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中的成员