时间:2018/11/28
地点:元征总部
天气:多云
笔记
1.#undef:#undef完成与#define相反的工作,它取消对传入的参数的宏定义
#define MAX_WIDTH 100
char str[MAX_WIDTH];
#undef MAX_WIDTH
2.#line:使编译器在出错时显示文件中的行数及文件名
(1)格式:#line number "filename"
number是将会赋值给下一行的新行数。它后面的行数从这一点逐个递增
filename是一个可选参数,用来替换自此行以后出错时显示的文件名,直到有另外一个#line指令替换它或直到文件的末尾
(2)例如:
#line 1 "assigning variable"
int a?;
//这段代码将会产生一个错误,显示为在文件"assigning variable",line 1
3.#error:这个指令将中断编译过程并返回一个参数中定义的出错信息,例如:
#ifndef __cplusplus
#error A C++ compiler is required
#endif
//这个例子中如果__cplusplus没有被定义就会中断编译过程
4.#include
(1)#include "file":编译器首先在包含这条指令的文件所在的目录下进行寻找,如果找不到指定文件,编译器再到配置
的默认路径下(也就是标准头文件路径下)进行寻找。
(2)#include <file>:编译器会直接到默认标准头文件路径下寻找。
5.#pragma
这个指令是用来对编译器进行配置的,针对你所使用的平台和编译器而有所不同。要了解更多信息,请参考你的编译器手册
。如果你的编译器不支持某个#pragma的特定参数,这个参数会被忽略,不会产生出错。
6.预定义的宏名称
以下宏名称在任何时候都是定义好的:
macro | value |
---|---|
_LINE_ | 整数值,表示当前正在编译的行在源文件中的行数 |
_FILE_ | 字符串,表示被编译的源文件的文件名 |
_DATE_ | 一个格式为"Mmm dd yyyy"的字符串,存储编译开始的日期 |
_TIME_ | 一个格式为"hh:mm:ss"的字符串,存储编译开始的时间 |
__cplusplus | 整数值,所有C++编译器都定义了这个常量为某个值。如果这个编译器是完全遵守C++标准的,它的值应该等于或大于199711L,具体值取决于它遵守的是哪个版本的标准 |
7.C++通过以下几个类支持文件的输入输出:
(1)ofstream:写操作(输出)的文件类(由ostream引申而来)
(2)ifstream:读操作(输入)的文件类(由istream引申而来)
(3)fstream:可同时读写操作的文件类(由iostream引申而来)
8.打开文件:在C++中,打开的文件由一个流对象来表示
(1)操作:void open(const char *filename, openmode mode);
(2)mode是以下标识符的一个组合:
ios::in | 为输入(读)而打开文件 |
ios::out | 为输出(写)而打开文件 |
ios::ate | 初始位置:文件尾 |
ios::app | 所有输出附加在文件末尾 |
ios::trunc | 如果文件已存在则先删除该文件 |
ios::binary | 二进制方式 |
这些标识符可以被组合使用,中间以"|"间隔
(3)ofstream,ifstream和fstream所有这些类的成员函数open都包含了一个默认打开文件的方式,这三个类的默认方式各
不相同:
类 | 参数的默认方式 |
---|---|
ofstream | ios::out|ios::trunc |
ifstream | ios::in |
fstream | ios::in |ios::out |
(4)例子1:
ofstream file;
file.open("example.bin", ios::out|ios::app|ios::binary);
(5)例子2:以下方式与例子1效果相同
fstream file("example.bin", ios::out|ios::app|ios::binary);
(6)可以通过调用成员函数is_open()来检查一个文件是否已经被顺利打开:bool is_open();
它返回一个布尔值,为真代表文件已经被顺利打开,假则相反。
9.关闭文件:void close();10.写入读出文件中的数据
(1)写入文件:
#include <iostream>
#include <fstream>
int main()
{
ofstream examplefile("example.txt");
if(examplefile.is_open())
{
examplefile << "This is a line.\n";
examplefile << "This is another line.\n";
examplefile.close();
}
return 0;
}
(2)读出文件:
#include <iostream>
#include <stdlib.h>
#include <fstream>
using namespace std;
int main()
{
char buffer[BUFSIZ];
ifstream examplefile("example.txt");
if(!examplefile.is_open())
{
cout << "Error opening file";
exit(1);
}
while(!examplefile.eof())
{
examplefile.getline(buffer, 100);
cout << buffer << endl;
}
return 0;
}
10.状态标识符的验证:
标识符 | 含义 |
---|---|
bad() | 如果在?过程中出错,返回true。例如当我们要对一个不是打开为写状态的文件进行写入时,或者我们要写入的设备没有剩余空间的时候。 |
fail() | 除了与bad()同样的情况下会返回true以为,加上格式错误时也返回true,例如当想要读入一个整数,而获得了一个字母的时候。 |
eof() | 如果读文件到达文件末尾,返回true。 |
good() | 这是最通用的:如果调用以上任何一个函数返回true的话,此函数返回false。 |
clear() | 重置以上成员函数所检查的状态标志。 |
11.获得和设置流指针
(1)所有输入/输出流对象都有至少一个流指针:
1)ifstream:类似istream,有一个被称为get point的指针,指向下一个将被读取的元素
2)ofstream:类似ostream,有一个指针put point,指向写入下一个元素的位置
3)fstream:类似iostream,同时继承了get和put
(2)可以使用以下成员函数来读出或配置这些指向流中读写位置的流指针:
1)tellg()和tellp()
这两个成员函数不用传入参数,返回pos_type类型的值(根据ANSI-C++标准),就是一个整数,代表当前get流
指针的位置(用tellg)或put流指针的位置(用tellp)。
2)seekg()和seekp()
这对函数分别用来改变流指针get和put的位置。两个函数都被重载为两种不同的原型:
seekg(pos_type position);
seekp(pos_type position);
使用这个原型,流指针被改变为指向从文件开始计算的一个绝对位置。要求传入的参数类型与函数tellg和tellp的返回类型相同。
seekg(off_type offset, seekdir direction);
seekp(off_type offset, seekdir direction);
使用这个原型可以指定由参数direction决定的一个具体的指针开始计算的一个位移(offset)。它可以是:
ios::beg | 从流开始位置计算的位移 |
ios::cur | 从流指针当前位置开始计算的位移 |
ios::end | 从流末尾处开始计算的位移 |
(3)流指针get和put的值对文本文件和二进制文件的计算方法都是不同的,因为文本模式的文件中某些特殊字符可能被修
改。由于这个原因,建议对文本文件模式打开的文件总是使用seekg和seekp的第一种原型,而且不要对tellg或tellp的返回
值进行修改。对二进制文件,可以任意使用这些函数,应该不会有任何意外的行为产生。
(4)使用这些函数来获得一个二进制文件的大小:
#include <iostream>
#include <fstream>
using namespace std;
const char * filename = "example.txt";
int main()
{
long l,m;
ifstream file(filename, ios::in|ios::binary);
l = file.tellg();
file.seekg(0,ios::end);
m = file.tellg();
file.close();
cout << "size of " << filename;
cout << " is " << (m-l) << " bytes.\n";
return 0;
}
12.二进制文件
(1)读写操作:
write(char *buffer, streamsize size);
read(char *buffer, streamsize size);
(2)例子:
#include <iostream>
#include <fstream>
using namespace std;
const char * filename = "example.txt";
int main()
{
char *buffer;
long size;
ifstream file(filename, ios::in|ios::binary|ios::ate);
size = file.tellg();
file.seekg(0, ios::beg);
buffer = new char[size];
file.read(buffer, size);
file.close();
cout << "the complete file is in a buffer";
delete[] buffer;
return 0;
}
13.缓存和同步
(1)当对文件流进行操作的时候,它们与一个streambuf类型的缓存联系在一起。这个缓存实际是一块内存空间,作为流和
物理文件的媒介。例如,对于一个输出流,每次成员函数put(写一个单个字符)被调用,这个字符不是直接被写入该输出
流所对应的物理文件中的, 而是首先被插入到该流的缓存中。
(2)当缓存被排放出来时,它里面的所有数据或者被写入物理媒介中(如果是一个输出流的话),或者简单的被抹掉(如
果是一个输入流的话)。这个过程称为同步,它会在以下任一情况下发生:
1)当文件被关闭时:在文件被关闭之前,所有还没被完全写出货读取的缓存都将被同步。
2)当缓存buffer满时:缓存buffers有一定的空间限制。当缓存满时,它会被自动同步。
3)控制符明确指明:当遇到流中某些特定的控制符时,同步会发生。这些控制符包括:flush和endl
4)明确调用函数sync():调用成员函数sync()(无参数)可以引发立即同步。这个函数返回一个int值,等于-1表
示流没有联系的缓存或操作失败。