先看一段C++中读取文件的程序(Linux下,如下:
#include<iostream>
#include<fstream>
#include<string>
#include<cstdlib>
using namespace std;
int main(){
ifstream fin;
fin.open("./tom.txt");
if(fin.is_open() == false){
exit(EXIT_FAILURE);
}
string buf;
int count = 0;
getline(fin, buf, ':');//读取文件内容,以':'字符确定输入的边界
while(fin){
++count;
cout << count << ": " << buf <<endl;
getline(fin, buf, ':');
}
cout << "Over!\n";
fin.close();
return 0;
}
文件内容:
abcd:is string:like a bear:
so:do you think sosososo!:
ll:
输出如下:
首先getline()函数是C++ string版本中独立的函数,函数声明如下:
istream& getline (istream& is, string& str, char delim);
istream& getline (istream& is, string& str);
getline()函数从输入中读取字符,并将其存储到string中,当发生下面三种情况时:
1、到达文件尾时,输入流的eofbit将被设置,意味着fail()与eof()都将返回true;
2、遇到分解字符时,将分解字符从输入流中删除,但不存储它;
2、读取的字符数达到最大允许值时,将设置输入流的failbit,意味着方法fail()返回true;
第一个参数接收的是istream类型的引用,而上述读取文件中传入的是ifstream类型,经过查阅资料得知两者有继承关系:
C++在处理C-风格字符串中也有一个名为getline()的函数,但这个函数是istream类的方法,而不是全局函数:
其声明如下:
istream& getline (char* s, streamsize n ); //分界字符为'\n'
istream& getline (char* s, streamsize n, char delim ); // 自定义分界字符
同时到达文件尾时,函数将设置输入流的eofbit,这意味着fail()与eof()都将返回true;
注: istream的状态标志的类型:
void reserve (size_t n = 0);
string版本的getline()函数有自动调整大小的功能,不需要指定读取多少个字符的数值参数:
string字符串,当程序将一些字母附加到字符串末尾时将发生什么呢?
不仅将已有字符串加大,因为相邻的内存可能被占用了。因此,可能需要分配一个新的内存块,并将原来的内容复制到新的内存单元中,但这样操作效率会非常低,因此很多C++实现分配一个比实际字符串大的内存块,为字符串提供更大的空间。当字符串的不断增大,超过了内存快的大小,程序将分配一个大小为原来两倍的新内存块,以提供足够大的空间,避免不断地分配新的内存块。
size_t capacity() const; //返回当前分配给字符串的内存块大小;
void reserve (size_t n = 0); //让你能够请求内存块的最小大小;
而利用C-风格字符串怎么实现类似string版本字符串自动调整大小的功能呢???
在redis中的SDS(简单动态字符串)就可以实现此功能,如下:
数据结构:
struct sdshdr {
// buf 中已占用空间的长度
int len;
// buf 中剩余可用空间的长度
int free;
// 数据空间
char buf[];
};
优点:
1、常数复杂度获取字符串长度(SDS中的len属性);
2、杜绝缓冲区溢出(自动将SDS的空间扩展1至所需大小);
3、减少修改字符串时带来的内存重新分配次数(a、空间预分配 b、惰性空间释放);
4、存储二进制安全(len属性决定字符串长度,不以'\0'判断结尾);
5、兼容部分C字符串函数(SDS保存的数据的末尾设置为空字符,在为buf分配空间时多分配一个字符存储空字符);
OVER...... 原创,欢迎指正。。。