C++ 如何检查 StringStream 变量是否为空/空?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8046357/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I check if a StringStream variable is empty/null?
提问by cr8ivecodesmith
Just a quick question here guys. I've been searching to no avail so far.
伙计们,这里只是一个简单的问题。到目前为止,我一直在寻找无济于事。
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.
我想检查它是否被分配了一个值。
回答by AusCBloke
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()
可用于获取准备好从 a 读入的可用字符数stringstream
,您可以使用它来检查您stringstream
是否为“空”。我假设您实际上并没有尝试检查 value 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
从 a 中提取 anstringstream
然后查看是否有任何剩余字符(即非数字),您可以检查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.
这与您正在尝试做的事情相似吗?我不确定是否有更好的方法,但我过去做过这个,对我来说效果很好。
https://en.cppreference.com/w/cpp/io/basic_streambuf/in_avail
https://en.cppreference.com/w/cpp/io/basic_streambuf/in_avail
EDIT:I see you just updated your question as I posted.
编辑:我看到您刚刚在我发布时更新了您的问题。
回答by SvSharma
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());
}
回答by oferei
This method is efficient and should work with output strings as well:
这种方法很有效,也应该与输出字符串一起使用:
ostringstream report_string;
if (report_string.tellp() == 0) {
// do something
}
回答by bdonlan
One way would be to check the size of the internal stringand 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
规范可能进一步限制了这一点;我没有详细检查过)。
回答by Liouvetren
Use eof() instead.
使用 eof() 代替。
Sample Code:
示例代码:
stringstream report_string;
if ( !(report_string.eof()) )
cout << "report_string EMPTY! \n";
回答by Tony Delroy
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 extractedfrom the stream, ignoring input that's already been successfullyparsed/extracted
- that's different from testing
report_string.str().empty()
, which still "sees" already-extracted input
- that's different from testing
if earlier parsing left the stream in a
fail
state you haven'tclear()
ed, this will returneof()
regardless of whether there are more unextracted characters
这会查找尚未从流中提取的字符,忽略已成功解析/提取的输入
- 这与 testing 不同
report_string.str().empty()
,它仍然“看到”已经提取的输入
- 这与 testing 不同
如果较早的解析使流处于
fail
您尚未clear()
编辑的状态,则eof()
无论是否有更多未提取的字符,这都会返回
回答by Richard Hodges
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)
不用的
stringstream
时候没有重复建设。如果随后使用未使用的字符串流(通过 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
的optional
,但你可以很容易地使用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;
}
回答by Nikolaj
I know that this question is very old and already answered, but depending on the situation there might also be yet another approach worth considering:
我知道这个问题很老并且已经回答了,但根据情况,可能还有另一种值得考虑的方法:
When you are testing if a stringstream is empty, you properly intend to do something with either the individual strings or each line in the stringstream; thus you will most likely be using either the >>
operator or std::getline
on the stringstream... and if the stream is empty these simply have the value false, thus you could write:
当您测试 stringstream 是否为空时,您正确地打算对 stringstream 中的单个字符串或每一行执行某些操作;因此,您很可能会使用>>
运算符或std::getline
字符串流……如果流为空,则这些值仅具有 false 值,因此您可以编写:
stringstream report_string;
foo(report_string)// some functions which may or may not write to report_string
string single_report;//string to read to
bool empty=true;//First assume it was empty
while(getline(report_string,single_report))//Alternatively use report_string>>single_report if you don't want entire lines
{
empty=false;//...it wasn't empty
bar(single_report);//Do whatever you want to do with each individual appended line
}
if (empty)
{
//... whatever you want to do if the stream was empty goes here
}
It should be noted that this approach assumes that you were planning on cycling through the stringstream; if you were not, then this approach can't be used.
应该注意的是,这种方法假设您计划在字符串流中循环;如果不是,则无法使用此方法。