我的问题很简单,getline(istream,string)是如何实现的? 你如何解决像getline(char * s,streamsize n)这样固定大小的char数组的问题? 他们是否使用临时缓冲区和许多调用新char [length]或其他整齐的结构?
答案 0 :(得分:7)
getline(istream&, string&)
以读取行的方式实现。它没有明确的实施;每个图书馆可能彼此不同。
可能的实施:
istream& getline(istream& stream, string& str)
{
char ch;
str.clear();
while (stream.get(ch) && ch != '\n')
str.push_back(ch);
return stream;
}
答案 1 :(得分:5)
@SethCarnegie是对的:可以实现多个实现。 C ++标准没有说明应该使用哪个。
然而,问题仍然很有趣。这是一个典型的计算机科学问题。当一个人事先不知道要分配多少内存时,在哪里以及如何分配内存?
一种解决方案是将字符串的字符记录为单个字符的链接列表。这既不是内存效率也不是快速,但它有效,稳健,编程相对简单。但是,标准库不太可能以这种方式实现。
第二种解决方案是分配一些固定长度的缓冲区,例如128个字符。当缓冲区溢出时,您分配一个双倍长度,256个字符的新缓冲区,然后将旧字符复制到新存储区,然后释放旧缓冲区。当新缓冲区溢出时,再次分配一个双倍长度的更新缓冲区,512个字符,然后重复该过程;等等。
第三种解决方案结合了前两种。保持字符数组的链接列表。列表的前两个成员(例如)每个成员128个字符。第三个存储256.第四个存储512,依此类推。这需要比其他编程更多的编程,但根据应用程序的不同,可能更好。
可能的实施清单继续。
关于标准库实现,@ SteveJessop补充说“由于operator[]
对字符串的复杂性要求,”[a]标准库的字符串不允许实现为(1)。在C ++中11由于字符串的连续性要求,不允许将其作为(3)实现.C ++委员会表示相信在添加邻接要求时没有活跃的C ++实现(3)。当然,{{ 1}}可以在将字符全部添加到字符串之前用字符暂时执行它喜欢的操作,但标准确实说明了字符串可以做什么。“
添加是相关的,因为尽管getline
可以以多种方式临时存储其数据,但如果数据的最终目标是字符串,这可能与getline
的实现相关。 @SteveJessop进一步补充说,“对于字符串本身来说,除了可以选择自己的扩展速率之外,它们几乎都需要实现;只要它们乘以某个常量,它们就不必每次都加倍。”
答案 2 :(得分:0)
正如@ 3bdalla所说,thb的实现不能作为gnu的实现。因此,我编写了自己的实现,其工作方式类似于gnu的实现。我不知道此变体中会出现什么错误,因此需要对其进行测试。 我对getline的实现:
std::istream& getline(std::istream& is, std::string& s, char delim = '\n'){
s.clear();
char c;
std::string temp;
if(is.get(c)){
temp.push_back(c);
while((is.get(c)) && (c != delim))
temp.push_back(c);
if(!is.bad())
s = temp;
if(!is.bad() && is.eof())
is.clear(std::ios_base::eofbit);
}
return is;
}