- 首先介绍第一个概念,缓冲区。使用缓冲区可以高效的处理输入与输出。缓冲区是用作中介的内存块,它是将信息从设备传输到程序或者从程序传输给设备的临时存储工具。
- 关于 put 和write
cout.put('W');
cout.put(65);
cout.put(65.5); //会将65.5转换成65
cout.write();
basic_ostream<charT,traits>& write(const char_type* s, streamsize n);
//第一个参数提供了要显示的字符串的地址。第二个参数指出要显示多少字符。返回类型为ostream&。
- 注意:write()方法并不会在遇到空字符时自动停止打印字符,而只是打印指定数目的字符,即使超过了字符串的边界。
- 使用cout 进行格式化
- 要控制整数以十进制、十六进制还是八进制显示,可以使用dec、hex和oct控制符。
hex(cout);
cout<<hex;
int width(); //返回字段宽度的当前设置
int width(int i); //将字段设置为i个空格,并返回以前的字段宽度值。
- 注意:width()方法只影响将显示的下一个项目,然后字段宽度将恢复为默认值。
- 填充字符
cout.fill('*');
- **注意:与字段宽度不同的是,新的填充字符将一直有效,直到它更改为止。
- 浮点数精度,c++的默认精度为6位(但末尾的0将不显示)。
cout.precision(2);
- 注意:新的精度设置将一直有效,直到被重新设置。
- 打印末尾的0和小数点
cout.setf(ios_base::showpoint);
- 使用默认的默认的浮点格式时,上述语句还将导致末尾的0被显示出来。
fmtflags setf(fmtflags);
常量 | 含义 |
---|
ios_base::boolalpha | 输入和输出bool值,可以为true或false |
ios_base::showbase | 对于输出,使用c++基数前缀(0,0x) |
ios_base::showpoint | 显示末尾的小数点 |
ios_base::uppercase | 对于16进制输出,使用大写字母,E表示法 |
ios_base::showpos | 在正数前面加上+ |
fmtflag setf(fmtflags,fmtflags);
- 第一个参数是一个包含了所需设置的fmtflags值。第二个参数指出要清除第一个参数中的那些位。
- c++在头文件 iomanip 中提供了其他一些控制符。最常用的控制符是 setprecision()、setfill()、setw(),分别是设置精度、填充字段和字段宽度。
- 流状态由3个ios_base 元素组成:eofbit、badbit、failbit。其中每个元素都是一位,可以是1(设置)或0(清除)。当cin操作到达文件末尾时,它将设置eofbit;当cin操作未能读取到预期的字符时,它将设置failbit。I/O失败的时候(如试图读取不可访问的文件或者试图写入写保护的磁盘),也可能将failbit设置为1。当三个状态位都设置为0的时候,说明一切顺利。
成员 | 描述 |
---|
eofbit | 如果到达文件尾,则设置为1 |
badbit | 如果流破坏,则设置为1;例如,文件读取错误 |
failbit | 如果输入操作未能读取预期的字符或输出操作没有写入预期的字符,则设置为1 |
eof() | 如果eofbit 被设置,则返回true |
bad() | 如果badbit 被设置,则返回true |
fail() | 如果badbit 或者 failbit 被设置,则返回true |
- 单字符输入,get()方法读取下一个字符,即使该字符时空格、制表符或者是换行符。get(char& ch)版本将输入字符赋给其参数,而get(void) 版本将输入字符转换为整形(通是int),并将其返回。
特征 | cin.get(ch) | ch = cin.get() |
---|
传输输入字符的方法 | 赋给参数ch | 将函数返回值赋给ch |
字符输入时函数的返回值 | 指向 istream 对象的引用 | 字符编码 (int 值) |
达到文件尾时函数的返回值 | 转换为false | EOF |
- get( char& ) 、 get( void ) 或 >> 。如果跳过空白更方便,则使用抽取运算符 >> ,如果希望程序检查每个字符,可以使用get方法
- 字符串输入
istream& get(char*, int, char );
istream& get(char*, int );
istream& getline(char*, int, char );
istream& getline(char*, int );
- 第一个参数是用于放置输入字符串的内存单元的地址。第二个参数比要读取的最大字符串数大1(额外的一个字符用于存储结尾的空字符,以便将输入存储为一个字符串)。第三个参数指定用作分界符的字符。注意:只有两个参数的版本将换行符作为分界符。 上述函数在读取最大数目的字符或遇到换行符后为止。
- get()和getline() 的主要区别在于,get()将换行符留在输入流中,这样接下来输入操作首先看到的是换行符,而getline()抽取并丢弃输入流中的换行符。并且和默认情况一样,get()将分界字符留在队列中,而getline()不保留。
- ignore()函数:该函数接收两个参数。一个是数字,指定要读取的最大字符数;另一个是字符,用作输入分界符。
- 其他的istream方法
- read()函数读取指定数目的字节,并将他们存储在指定的位置中。
- peek() 函数返回输入中的下一个字符,但是不抽取输入流中的字符。也就是说,它使得能够查看下一个字符。假设要读取输入,直到遇到换行符或这句点,则可以使用peek() 查看输入流中的下一个字符。
- 文件的输入与输出
- 头文件 #include< fstream >
ofstream fout;
fout.open("jar.txt");
//或者
ofstream fout("jar.txt");
- 以上面的方式打开文件来输入输出时,如果没有这样的文件,将创建一个新文件;如果有这样的文件,则打开文件将清空文件,输出将进入到一个空文件中。
- 流状态检查和 is_open()
if( fin.fail() ) ... //fail to open
if( !fin.good() ) ... //failed to open
if( !fin ) .... //failed to open
if( !fin.is_open() ) ...
- 上述的前三种方法是等价的,并且都是有缺陷的。就是这些测试无法检测到这样一种情形:试图以不合适的文件模式打开文件时失败。而最后一种方法 is_open() 可以检测到所有问题。
- 文件模式
常量 | 含义 |
---|
ios_base::in | 打开文件,以便读取 |
ios_base::out | 打开文件,以便写入 |
ios_base::ate | 打开文件,并移到文件尾 |
ios_base::app | 追加到文件尾 |
ios_base::trunc | 如果文件存在,则裁短文件 |
ios_base::binary | 二进制文件 |
- 文本格式便于读取,可以使用编辑器或者字处理器来读取和编辑文本文件,可以很方便地将文本文件从一个计算机系统传输到另一个计算机系统。二进制格式对于数字来说比较精确,因为它存储的值的内部表示,因此不会有转换误差或者舍入误差。以二进制保存数据的速度更快,因为不需要转换,并可以大块的存储数据。二进制格式通常占用的空间较小,这取决与数据的特征。
- 二进制和文本文件
- 使用二进制文件模式时,程序从内存传输给文件时,将不会发生任何隐藏的转换,而默认的文本模式并非如何。例如:Windows 文本文件,他们使用两个字符的组合(回车和换行)表示换行符;而Unix和linux 文件使用换行来表示换行符。C++也使用换行来表示换行符,因此为了增加可移植性,windows c++程序在写文本文件时,自动将c++换行符转换为回车和换行。在读取文件时,这些程序将本地换行符转换为c++格式。对于二进制数据,文本格式会引起问题,因此double值中间的字节可能与换行符的ASCII 码有相同的位模式。另外,在文件尾的检测方式也有区别。因此二进制格式保存数据时,应使用二进制文件模式。
- 要以二进制格式存储数据,可以使用write() 成员函数,这种方法将内存中指定数目的字节复制到文件中。它只是逐字节的复制数据,而不进行任何转换。例如:如果将一个long 变量的地址传递给它,并命令它复制4个字节,它将复制long 值中的4个字节,而不会将它转行成文本。唯一不便的地方是,必须将地址强制转换为指向char的指针。也可以以同样的方式来复制整个结构体。但是,这种方法不适用有虚函数的类。对于没有虚函数的类,只有数据成员被保存,而方法不会被保存。如果类中有虚方法,则也将复制隐藏指针(该指针指向虚函数的指针表)。由于下一次运行程序时,虚函数表可能在不同的位置,因此将文件中的旧指针信息复制到对象中,将可能造成混乱。
- 需要注意的一点就是,在保存的时候,一定要看清楚保存的是数据本身还是数据的地址,如果保存的是地址,那么当再次运行程序时,这个地址将毫无意义。
- 介绍两个函数seekg()和seekp(),前者将输入指针移到指定的文件位置,后者将输出指针移到指定的文件位置。(实际上,由于fstream类使用缓冲区来存储中间数据,因此指针指向的是缓冲区中的位置,而不是实际的文件)。也可以将seekg()用于ifstream 对象,将seekp()用于ofstream对象。
istream & seekg( streamoff, ios_base::seekdir ) ;
istream & seekg( streampos );
- 上面的第一个原型定为到离第二个参数指定的文件位置特定距离(单位为字节)的位置;第二个原型定位到离文件开头特定距离(单位为字节)的位置。streamoff值用来度量相对于文件特定位置的偏移量(单位是字节)。seek_dir参数是ios_base 类中定义的另一种整形,有3个可能的值。常量ios_base::beg 指相对于文件开始处的偏移量。常量ios_base::cur 指相对于当前位置的偏移量;常量ios_base::end指相对于文件尾的偏移量。streampos类型的值定位到文件中的一个位置。它可以是类,但如果是这样的话,这个类将包含一个接受streamoff参数的构造函数和一个接受整数参数的构造函数,以便将两种类型转换为streampos值。streampos 值表示文件中的绝对位置(从文件开始处算起)。
- 如果要检查文件指针的当前位置,则对于输入流,可以使用tellg()方法,对于输出流,可以使用tellp() 方法,他们都返回一个表示当前位置的streampos值(以字节为单位,从文件开始算起)。
- 在介绍一个函数
char* tmpnam( char* pszName );
- tmpNam() 函数创建一个临时文件名,将它放在pszName指向的C-风格字符串中。常量L_tmpnam和TMP_MAX(二者都是在cstdio中定义的)限制了文件名包含的字符数以及在确保当前目录中不可重复文件名的情况下tmpnam()可被调用的最多次数。
#include<cstdio>
#include<iostream>
int main()
{
char pszName[L_tmpnam] = { '\0' };
std::cout << "Here are ten names:\n";
for (int i = 0; i < 10; ++i)
{
tmpnam(pszName);
std::cout << pszName << std::endl;
}
return 0;
}
- 在提一点,就是关于内核格式化的类。ostringstream 和 istringstream 类等等,这些类使得能够使用istream 和 ostream 方法来抽取字符串中的信息,并对要放入到字符串中的信息进行格式化。