getline的实现(istream&is,string&str)

问题描述 投票:6回答:3

我的问题很简单,如何实现getline(istream,string)?如何解决具有固定大小的字符数组(如getline(char * s,streamsize n))的问题?他们在使用临时缓冲区以及对新char [length]或其他整洁结构的许多调用吗?

c++ string
3个回答
8
投票

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;
}

5
投票

@@ SethCarnegie是正确的:可以实现多种实现。 C ++标准未说明应使用哪个。

但是,这个问题仍然很有趣。这是一个经典的计算机科学问题。当一个人事先不知道要分配多少内存时,该在哪里分配内存以及如何分配内存?

  1. 一种解决方案是将字符串的字符记录为单个字符的链表。这既不节省内存,也不快速,但是它有效,可靠并且编程相对简单。但是,标准库不太可能以这种方式实现。

  2. 第二种解决方案是分配某个固定长度的缓冲区,例如128个字符。当缓冲区溢出时,您将分配一个新的双倍长度(256个字符)的缓冲区,然后将旧字符复制到新存储中,然后释放旧缓冲区。当新缓冲区溢出时,您将再次分配一个更长的双倍缓冲区(512个字符),然后重复该过程;依此类推。

  3. 第三个解决方案结合了前两个。保留字符数组的链接列表。列表的前两个成员每个存储(例如)128个字符。第三存储区256。第四存储区512,依此类推。这需要比其他程序更多的编程,但根据应用程序的不同,可能比其中任何一种都更合适。

以及可能的实现列表继续。

关于标准库的实现,@ SteveJessop补充说:“由于operator[]对字符串的复杂性要求,不允许将[a]标准库的字符串实现为(1)。在C ++ 11中,它不是由于对字符串的连续性要求,因此允许将其实现为(3)。C++委员会表示相信,在添加连续性要求时,没有活动的C ++实现会执行(3),当然getline可以在将所有字符全部添加到字符串之前,暂时不喜欢这些字符,但是标准确实说明了字符串可以做什么。”

之所以具有相关性,是因为尽管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;
}
热门问题
推荐问题
最新问题