如何检查StringStream变量是否为空/ null?

时间:2021-11-28 07:19:14

Just a quick question here guys. I've been searching to no avail so far.

这里只是一个简单的问题。到目前为止,我一直在寻找无济于事。

Thanks!

谢谢!

A bit more info here:

这里有更多信息:

stringstream report_string;

report_string << "some string here...";

In my code itself are various conditions for assigning values to the report_string variable.

在我的代码中,有各种条件为report_string变量赋值。

I'd like to check whether it was assigned a value or not.

我想检查它是否被赋值。

7 个解决方案

#1


34  

myStream.rdbuf()->in_avail() can be used to get the count of available characters ready to be read in from a stringstream, you can use that to check if your stringstream is "empty." I'm assuming you're not actually trying to check for the value null.

myStream.rdbuf() - > in_avail()可用于获取准备从字符串流中读取的可用字符的数量,您可以使用它来检查您的字符串流是否为“空”。我假设你实际上并没有尝试检查null值。

For example if you want to extract an int from a stringstream and then see if there were any left over characters (ie. non-numeric) you could check if myStream.rdbuf()->in_avail() == 0.

例如,如果要从字符串流中提取int,然后查看是否有任何遗留字符(即非数字),您可以检查myStream.rdbuf() - > in_avail()== 0。

Is that something similar to what you're trying to do? I'm not sure if there's better ways but I've done this in the past and it's worked fine for me.

这与你想做的事情类似吗?我不确定是否有更好的方法,但我过去做过这件事,这对我来说很好。

EDIT: I see you just updated your question as I posted.

编辑:我看到你刚刚发布时更新了你的问题。

#2


5  

One way would be to check the size of the internal string and compare against zero. Note that this is different from myStream.rdbuf()->in_avail() as AusCBlock suggests; in_avail() can return a value different from the actual size of the stream (if, for example, the internal buffer is represented with multiple non-contiguous memory blocks). In particular, in_avail() can, in principle, return zero in non-empty buffers (it's possible that the stringbuf specification restricts this further; I have no checked in that much detail).

一种方法是检查内部字符串的大小并与零进行比较。请注意,这与myStream.rdbuf() - > in_avail()不同,正如AusCBlock建议的那样; in_avail()可以返回一个与流的实际大小不同的值(例如,如果内部缓冲区用多个非连续的内存块表示)。特别是,in_avail()原则上可以在非空缓冲区中返回零(stringbuf规范可能会进一步限制这一点;我没有检查过那么多细节)。

#3


5  

An easy check would be to see if the string content of the stream is empty or not:

一个简单的检查是查看流的字符串内容是否为空:

#include<assert.h>
#include<sstream>

int main(){
std::stringstream report_string;
report_string << ""; // an empty strin g

//emptiness check of stringstream
assert(report_string.str().empty());
}

#4


4  

This method is efficient and should work with output strings as well:

此方法很有效,也应该与输出字符串一起使用:

ostringstream report_string;

if (report_string.tellp() == 0) {
    // do something
}

#5


2  

Use eof() instead.

请改用eof()。

Sample Code:

示例代码:

stringstream report_string;
if ( !(report_string.eof()) ) 
    cout << "report_string EMPTY! \n";

#6


1  

It's normally reasonable and readable to use...

这通常是合理的,可读的......

report_string.str().empty()

...but that may involve dynamic allocation and copying the entire string to a temporary, only to be thrown away.

...但这可能涉及动态分配并将整个字符串复制到临时字符串,只能被丢弃。

If performance is important, another option is...

如果表现很重要,另一种选择是......

report_string.peek() == decltype(report_string)::traits_type::eof()
  • this looks for a character not yet extracted from the stream, ignoring input that's already been successfully parsed/extracted

    这会查找尚未从流中提取的字符,忽略已成功解析/提取的输入

    • that's different from testing report_string.str().empty(), which still "sees" already-extracted input
    • 这与测试report_string.str()。empty()不同,后者仍然“看到”已经提取的输入
  • if earlier parsing left the stream in a fail state you haven't clear()ed, this will return eof() regardless of whether there are more unextracted characters

    如果之前的解析使流处于失败状态,你没有clear()ed,这将返回eof(),无论是否有更多未提取的字符

#7


0  

How about another approach?

另一种方法怎么样?

If you make the ostringstream an optional type you can check that its been assigned to before using it.

如果将ostringstream设置为可选类型,则可以在使用之前检查它是否已分配给它。

Imagine a class called lazy<> which lazily constructs an object when needed, then we could do this:

想象一个名为lazy <>的类,它在需要时懒惰地构造一个对象,然后我们可以这样做:

int main()
{
    using namespace std;

    auto oss1 = lazy<std::ostringstream>();
    auto oss2 = lazy<std::ostringstream>();

    use(oss1) << "Hello";

    if (oss1) cout << use(oss1).str() << endl;
    if (oss2) cout << use(oss2).str() << endl;

    if_used(oss1, [](auto& ss) { cout << ss.str() << endl; });
    if_used(oss2,
            [](auto& ss) { cout << ss.str() << endl; },
            [](auto& oss) { cout << "oss2 is not used" << endl; });

    use(oss2) << "Goodbye";
    if_used(oss2, [](auto& ss) { cout << ss.str() << endl; });

    return 0;
}

yielding this output:

产生这个输出:

Hello
Hello
oss2 is not used
Goodbye

Advantages:

优点:

  • no redundant construction of the stringstream when not used.

    没有使用时没有字符串流的冗余构造。

  • optional provides an exception if the unused stringstream is subsequently used (via const reference)

    如果随后使用未使用的字符串流,则可选提供异常(通过const引用)

Full example below with customisable constructor:

以下完整示例,可自定义构造函数:

I've used std::experimental for the optional, but you could just as easily use boost::optional.

我已经使用std :: experimental作为可选项,但你可以很容易地使用boost :: optional。

#include <iostream>
#include <experimental/optional>
#include <utility>
#include <type_traits>
#include <sstream>

using std::experimental::optional;

namespace detail {
    template<class T, class Constructor>
    struct lazy final
    {
        template<class Con , std::enable_if_t< not std::is_same<std::decay_t<Con>, lazy>::value > * = nullptr>
        lazy(Con&& con)
        : _constructor(std::forward<Con>(con))
        {}

        T& get() {
            if (not bool(_opt)) {
                _opt = _constructor();
            }
            return *_opt;
        }

        const T& get() const {
            return *_opt;
        }

        bool used() const {
            return bool(_opt);
        }

        operator bool() const {
            return used();
        }

    private:
        Constructor _constructor;
        optional<T> _opt;
    };

    template<class T>
    struct default_construct {
        T operator()() const { return T(); }
    };

    struct no_action {
        template<class T>
        void operator()(T&) const { }
    };
}


template<class T, class Constructor = detail::default_construct<T> >
auto lazy(Constructor&& con = detail::default_construct<T>())
{
    return detail::lazy<T, std::decay_t<Constructor>>(std::forward<Constructor>(con));
}

template<class T, class Constructor>
auto& use(detail::lazy<T, Constructor>& l)
{
    return l.get();
}

template<class T, class Constructor>
auto& use(const detail::lazy<T, Constructor>& l)
{
    return l.get();
}

template<class T, class Constructor, class F, class Else = detail::no_action>
void if_used(detail::lazy<T, Constructor>& l, F&& f, Else&& e = detail::no_action())
{
    if (l.used())
        f(l.get());
    else
        e(l);
}

template<class T, class Constructor, class F, class Else = detail::no_action>
void if_used(const detail::lazy<T, Constructor>& l, F&& f, Else&& e)
{
    if (l.used())
        f(l.get());
    else
        e(l);
}

int main()
{
    using namespace std;

    auto oss1 = lazy<std::ostringstream>();
    auto oss2 = lazy<std::ostringstream>();

    use(oss1) << "Hello";

    if (oss1) cout << use(oss1).str() << endl;
    if (oss2) cout << use(oss2).str() << endl;

    if_used(oss1, [](auto& ss) { cout << ss.str() << endl; });
    if_used(oss2,
            [](auto& ss) { cout << ss.str() << endl; },
            [](auto& oss) { cout << "oss2 is not used" << endl; });

    use(oss2) << "Goodbye";
    if_used(oss2, [](auto& ss) { cout << ss.str() << endl; });

    return 0;
}

#1


34  

myStream.rdbuf()->in_avail() can be used to get the count of available characters ready to be read in from a stringstream, you can use that to check if your stringstream is "empty." I'm assuming you're not actually trying to check for the value null.

myStream.rdbuf() - > in_avail()可用于获取准备从字符串流中读取的可用字符的数量,您可以使用它来检查您的字符串流是否为“空”。我假设你实际上并没有尝试检查null值。

For example if you want to extract an int from a stringstream and then see if there were any left over characters (ie. non-numeric) you could check if myStream.rdbuf()->in_avail() == 0.

例如,如果要从字符串流中提取int,然后查看是否有任何遗留字符(即非数字),您可以检查myStream.rdbuf() - > in_avail()== 0。

Is that something similar to what you're trying to do? I'm not sure if there's better ways but I've done this in the past and it's worked fine for me.

这与你想做的事情类似吗?我不确定是否有更好的方法,但我过去做过这件事,这对我来说很好。

EDIT: I see you just updated your question as I posted.

编辑:我看到你刚刚发布时更新了你的问题。

#2


5  

One way would be to check the size of the internal string and compare against zero. Note that this is different from myStream.rdbuf()->in_avail() as AusCBlock suggests; in_avail() can return a value different from the actual size of the stream (if, for example, the internal buffer is represented with multiple non-contiguous memory blocks). In particular, in_avail() can, in principle, return zero in non-empty buffers (it's possible that the stringbuf specification restricts this further; I have no checked in that much detail).

一种方法是检查内部字符串的大小并与零进行比较。请注意,这与myStream.rdbuf() - > in_avail()不同,正如AusCBlock建议的那样; in_avail()可以返回一个与流的实际大小不同的值(例如,如果内部缓冲区用多个非连续的内存块表示)。特别是,in_avail()原则上可以在非空缓冲区中返回零(stringbuf规范可能会进一步限制这一点;我没有检查过那么多细节)。

#3


5  

An easy check would be to see if the string content of the stream is empty or not:

一个简单的检查是查看流的字符串内容是否为空:

#include<assert.h>
#include<sstream>

int main(){
std::stringstream report_string;
report_string << ""; // an empty strin g

//emptiness check of stringstream
assert(report_string.str().empty());
}

#4


4  

This method is efficient and should work with output strings as well:

此方法很有效,也应该与输出字符串一起使用:

ostringstream report_string;

if (report_string.tellp() == 0) {
    // do something
}

#5


2  

Use eof() instead.

请改用eof()。

Sample Code:

示例代码:

stringstream report_string;
if ( !(report_string.eof()) ) 
    cout << "report_string EMPTY! \n";

#6


1  

It's normally reasonable and readable to use...

这通常是合理的,可读的......

report_string.str().empty()

...but that may involve dynamic allocation and copying the entire string to a temporary, only to be thrown away.

...但这可能涉及动态分配并将整个字符串复制到临时字符串,只能被丢弃。

If performance is important, another option is...

如果表现很重要,另一种选择是......

report_string.peek() == decltype(report_string)::traits_type::eof()
  • this looks for a character not yet extracted from the stream, ignoring input that's already been successfully parsed/extracted

    这会查找尚未从流中提取的字符,忽略已成功解析/提取的输入

    • that's different from testing report_string.str().empty(), which still "sees" already-extracted input
    • 这与测试report_string.str()。empty()不同,后者仍然“看到”已经提取的输入
  • if earlier parsing left the stream in a fail state you haven't clear()ed, this will return eof() regardless of whether there are more unextracted characters

    如果之前的解析使流处于失败状态,你没有clear()ed,这将返回eof(),无论是否有更多未提取的字符

#7


0  

How about another approach?

另一种方法怎么样?

If you make the ostringstream an optional type you can check that its been assigned to before using it.

如果将ostringstream设置为可选类型,则可以在使用之前检查它是否已分配给它。

Imagine a class called lazy<> which lazily constructs an object when needed, then we could do this:

想象一个名为lazy <>的类,它在需要时懒惰地构造一个对象,然后我们可以这样做:

int main()
{
    using namespace std;

    auto oss1 = lazy<std::ostringstream>();
    auto oss2 = lazy<std::ostringstream>();

    use(oss1) << "Hello";

    if (oss1) cout << use(oss1).str() << endl;
    if (oss2) cout << use(oss2).str() << endl;

    if_used(oss1, [](auto& ss) { cout << ss.str() << endl; });
    if_used(oss2,
            [](auto& ss) { cout << ss.str() << endl; },
            [](auto& oss) { cout << "oss2 is not used" << endl; });

    use(oss2) << "Goodbye";
    if_used(oss2, [](auto& ss) { cout << ss.str() << endl; });

    return 0;
}

yielding this output:

产生这个输出:

Hello
Hello
oss2 is not used
Goodbye

Advantages:

优点:

  • no redundant construction of the stringstream when not used.

    没有使用时没有字符串流的冗余构造。

  • optional provides an exception if the unused stringstream is subsequently used (via const reference)

    如果随后使用未使用的字符串流,则可选提供异常(通过const引用)

Full example below with customisable constructor:

以下完整示例,可自定义构造函数:

I've used std::experimental for the optional, but you could just as easily use boost::optional.

我已经使用std :: experimental作为可选项,但你可以很容易地使用boost :: optional。

#include <iostream>
#include <experimental/optional>
#include <utility>
#include <type_traits>
#include <sstream>

using std::experimental::optional;

namespace detail {
    template<class T, class Constructor>
    struct lazy final
    {
        template<class Con , std::enable_if_t< not std::is_same<std::decay_t<Con>, lazy>::value > * = nullptr>
        lazy(Con&& con)
        : _constructor(std::forward<Con>(con))
        {}

        T& get() {
            if (not bool(_opt)) {
                _opt = _constructor();
            }
            return *_opt;
        }

        const T& get() const {
            return *_opt;
        }

        bool used() const {
            return bool(_opt);
        }

        operator bool() const {
            return used();
        }

    private:
        Constructor _constructor;
        optional<T> _opt;
    };

    template<class T>
    struct default_construct {
        T operator()() const { return T(); }
    };

    struct no_action {
        template<class T>
        void operator()(T&) const { }
    };
}


template<class T, class Constructor = detail::default_construct<T> >
auto lazy(Constructor&& con = detail::default_construct<T>())
{
    return detail::lazy<T, std::decay_t<Constructor>>(std::forward<Constructor>(con));
}

template<class T, class Constructor>
auto& use(detail::lazy<T, Constructor>& l)
{
    return l.get();
}

template<class T, class Constructor>
auto& use(const detail::lazy<T, Constructor>& l)
{
    return l.get();
}

template<class T, class Constructor, class F, class Else = detail::no_action>
void if_used(detail::lazy<T, Constructor>& l, F&& f, Else&& e = detail::no_action())
{
    if (l.used())
        f(l.get());
    else
        e(l);
}

template<class T, class Constructor, class F, class Else = detail::no_action>
void if_used(const detail::lazy<T, Constructor>& l, F&& f, Else&& e)
{
    if (l.used())
        f(l.get());
    else
        e(l);
}

int main()
{
    using namespace std;

    auto oss1 = lazy<std::ostringstream>();
    auto oss2 = lazy<std::ostringstream>();

    use(oss1) << "Hello";

    if (oss1) cout << use(oss1).str() << endl;
    if (oss2) cout << use(oss2).str() << endl;

    if_used(oss1, [](auto& ss) { cout << ss.str() << endl; });
    if_used(oss2,
            [](auto& ss) { cout << ss.str() << endl; },
            [](auto& oss) { cout << "oss2 is not used" << endl; });

    use(oss2) << "Goodbye";
    if_used(oss2, [](auto& ss) { cout << ss.str() << endl; });

    return 0;
}