【问题标题】:How to properly empty stringstream buffer?如何正确清空字符串流缓冲区?
【发布时间】:2021-03-04 16:42:05
【问题描述】:

我已阅读How do you clear a stringstream variable? 以通过stringstream.str("") 清除缓冲区,或者换句话说 - 设置空字符串。但如果我这样做,它不会清除它:

date.hpp

#include <sstream>
#include <time.h>

#define fmt "%m/%d/%y"

class Date
{
    std::stringstream buffer;
    struct tm date;

    template <class T>
    void insertbuf(const T &);
    void inserttime();
    std::string getFromIn(std::istream &);

public:
    //ctors
    Date();
    Date(const char *str);
    Date(const std::string &s);
    Date(std::istream &in);
    Date(const Date &d);

    //operators
    Date &operator=(const Date &rhs);

    //general
    const std::string getAll() const;
    int getMonth() const;
    int getDay() const;
    int getYear() const;
};

日期.cpp

template <class T>
void Date::insertbuf(const T &val)
{
    if (!buffer.rdbuf()->in_avail())
    {
        buffer << val;
    }
}

void Date::inserttime()
{
    buffer >> std::get_time(&date, fmt);
}

Date &Date::operator=(const Date &rhs)
{
    if (&rhs != this)
    {
        buffer.str("");
        insertbuf<std::string>(rhs.buffer.str());
        inserttime();
    }
    return *this;
}

现在在函数insertbuf 中,只有在没有其他数据的情况下,我才会将&lt;&lt; 放到缓冲区中。所以在operator=,它的左侧(对象本身,或*this)在缓冲区中有一些数据,因此我必须清除它们。我试图通过将缓冲区设置为空字符串buffer.str("") 或等效的buffer.str(std::string()) 来做到这一点,但似乎不会设置它。从这里开始:

main.cpp

int main()
{
    Date bar = "11/23/2020";
    Date foo = "11/21/2020";
    cout << "before operator= " << foo.getAll() << endl;
    foo = bar;
    cout << "after operator= " << foo.getAll() << endl;
}

输出:

before operator= date: 11/21/2020
after operator= date: 11/21/2020

我可以看到operator= 函数中没有清除缓冲区,因为缓冲区没有改变(输出应该是11/23/2020insertbuf 函数可能没有通过if statement,因为缓冲区不为空,即使我将其设置为空字符串),为什么?那么如何正确清除std::stringstream的缓冲区呢?

一个例子: https://godbolt.org/z/h6zofr

问题背后的原因是: https://codereview.stackexchange.com/questions/252456/how-to-implement-simple-date-class-in-c

【问题讨论】:

  • 条件是避免foo = foo,或者自赋值。我不是在做自我分配,所以应该没问题
  • 请发帖minimal reproducible example。根据您发布的内容,我无法重现该问题:godbolt.org/z/v84oKa(忘记我的最后评论,这是无意义的;)
  • 好的,我不想在这里搞砸完整的实现,但我会尝试这样做,以便将粘贴链接粘贴到帖子中
  • 请在问题中包含minimal reproducible example。如果不想发太多代码,可以减少,但请确保你发的内容完整,以便他人重现你的问题
  • edit 你的minimal reproducible example 回答你的问题,而不是在 cmets 中作为链接发布

标签: c++ stream buffer stringstream


【解决方案1】:

您遇到的问题是调用buffer.str("") 不会重置流状态标志,因此如果先前的操作失败或到达流的末尾,其他读取将不会成功。以下应该可以解决问题:

buffer.str("");
buffer.clear();

您的代码似乎过于复杂。如果您要做的只是在字符串之间转换日期,我建议使用 Howard Hinnant 的 date 库,它现在也是 c++20 的一部分。

【讨论】:

  • 这只是为了学习实现类的目的,我当然会在实际项目中使用std-lib类作为日期
  • 无论如何,我对streambuf还不是很熟悉,不知道它的哪些标志很重要(否则我不会关心清除标志的clear())。你说,之前的操作失败了。我在代码中看不到任何地方,我从const char* 创建对象,stringstream 的缓冲区应该在哪里失败。那么为什么我必须清除标志,当缓冲区在任何地方都不应该失败时。你能解释一下吗?
  • 另外,缓冲区在主函数的哪个位置(行)“到达流的末尾”?在哪里? (只是想明白)
  • inserttimeeoffail 位设置为您的格式字符串不正确(应为%m/%d/%Y),即使使用更正的格式字符串,它仍将eof 标志设置为它读取到流的末尾
  • 问题背后的原因,在这里
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-05
  • 2013-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多