期中考试终于告一段落,再来继续写咯。
在前面说到过每一个iostream对象都有一个缓冲区,我们称之为流缓冲区,那个这个所谓的流缓冲区是怎么存在的呢?iostreams中将该流缓冲区抽象为一个类,即streambuf类。
每个iostream的类都会包含一个指向streambuf对象的指针,这也就意味着我们可以直接的去访问到这个指针,并向该streambuf对象发送消息等(但是一般情况下我们并不需要这样做)。
既然说我们可以得到这个指针,那isotreams类当然会提供访问的接口了,这就是const成员函数rdbuf(),它会返回iostream对象所有的streambuf也就是缓冲区的指针。那这个缓冲区的指针有什么用呢?最常用的就是直接对其进行输入输出操作,看下面的例子:
1.txt内容: hello world~~!! my name is zorro. nice to meet you~
int main() {ifstream fin("1.txt");
cout << fin.rdbuf() << endl;
system("pause");return 0;
}
上面的程序输出为:
可见对这个streambuf对象的指针进行输出操作,直接输出了缓冲区的所有内容,这是个很方便的功能。但是要注意的是,对rdbuf()返回的指针进行输出,一定得到的是整个缓冲区的内容吗?再看下面的例子:
int main() {ifstream fin("1.txt");string str;
fin >> str;
cout << fin.rdbuf() << endl;
system("pause");return 0;
}
上面的程序输出为:
可见对rdbuf()进行输出得到的并不一定是整个缓冲区的内容。为了对这个东西进行说明,我们必须先要了解缓冲区拥有的两个指针,我们一般称之为get指针和put指针。
对于streambuf类(其实就是basic_streambuf<char>类),可以看出它的操作是以字节(char)为单位的,所以get指针与put指针也是以字节为单位移动的。get指针指向的是缓冲区中下一个将要提取的字节,put指针指向的是向缓冲区中输出数据的下一个位置。可以通过成员函数seekg来移动get指针,seekp来移动put指针。当然从上面的描述我们可以看到,get指针是对输入的操作,put指针是对输出的操作,所以在类似ifstream这样的输入功能类中,是没有seekp函数只有seekg函数的,同样在ofstream也只有seekp函数没有seekg的。看下面的例子:
int main() {ifstream fin("1.txt");string str;
fin >> str;
fin.seekg(2,ios::beg);
cout << fin.rdbuf() << endl;
system("pause");return 0;
}
这个程序的输出为:
可见对于rdbuf()返回的指针的输出,并不是直接输出缓冲区中的所有内容,而是输出get指针后面的内容。
iostream同样提供了成员函数tellg和tellp,这两个函数返回的是当前get指针和put指针的位置,返回的类型是streampos,它们同样很有用,可以用来临时存储一个位置。看下面的例子:
#define PRINTCURPOS(in) cout << "cur pos:" << in.tellg() << endl#define PRINTANDEXEC(st) cout << #st << endl; stint main() {PRINTANDEXEC(ifstream fin("1.txt"));PRINTANDEXEC(string str);
PRINTCURPOS(fin);
PRINTANDEXEC(fin >> str);
PRINTCURPOS(fin);
PRINTANDEXEC(fin.seekg(2,ios::beg));
PRINTCURPOS(fin);
PRINTANDEXEC(cout << fin.rdbuf() << endl);
PRINTCURPOS(fin);
system("pause");return 0;
}
上面的程序输出为:
以上只演示了get指针的的使用,关于put指针的使用跟get指针差不多,就不赘述了。