handle empty string case extracting a string from std::istream

无人久伴 提交于 2020-01-02 08:15:20

问题


Using the following code to extract a string from a std::istream :

#include <sstream>
#include <iostream>

void parse(std::istream & is, std::string & out)
{
    is >> out;
}

int main(int argc, char** argv)
{
    if (argc>1)
    {
        std::istringstream is(argv[1]);
        std::string out("__INIT__");
        std::cout << "good:"  << is.good() << " fail:"<< is.fail() <<  " eof:"<< is.eof()  << " in_avail:"<< is.rdbuf()->in_avail() << " value:" << out << std::endl;
        parse(is, out);
        std::cout << "good:"  << is.good() << " fail:"<< is.fail() <<  " eof:"<< is.eof()  << " in_avail:"<< is.rdbuf()->in_avail() << " value:" << out << std::endl;
    }
}

With a non-empty string the output looks like :

$./a.out "TEST" 
good:1 fail:0 eof:0 in_avail:4 value:__INIT__
good:0 fail:0 eof:1 in_avail:0 value:TEST

With an empty string the output looks like :

$./a.out ""
good:1 fail:0 eof:0 in_avail:0 value:__INIT__
good:0 fail:1 eof:1 in_avail:0 value:__INIT__

Instead of this, I would expect :

good:1 fail:0 eof:0 in_avail:0 value:__INIT__
good:0 fail:0 eof:1 in_avail:0 value:

The operator>> does not extract an empty string. The result is the same with an empty string or and no data.

Any suggestion to handle this situation will be appreciated.


回答1:


If you're using your parse function exclusively for extraction, you can simply make it out to be a check for an empty buffer. If there is, simply clear the string:

void parse(std::istream& is, std::string& out)
{
    if (is.eof() || is.peek() == std::char_traits<char>::eof())
    {
        out.clear();
        return;
    }

    is >> out;
}



回答2:


There is no difference between an empty value and no value.

That's just your assumption, and it's not really true.

If you attempt to extract a string, it is expected that there are characters to extract. Before characters are available, it is impossible to perform any extraction, let alone one that results in extraction to a particular object.

This is entirely expected behaviour.

I guess your confusion stems from your prior check for argc > 1, but although the shell pretended ./myProgram "" had some argument, as far as your stream is concerned there is nothing in that argument.

If you wish to make your own handling for it, simply stick an if condition on is.fail() after the read.

#include <sstream>
#include <iostream>

int main(int argc, char** argv)
{
    if (argc>1)
    {
        std::istringstream is(argv[1]);
        std::string out;
        is >> out;

        if (is.fail()) {
           std::cout << "Well, you gave me an argument, but it was empty, biatch!\n";
        }
    }
}

Don't bother checking is.eof(); it'll be set when you reached the end of input whether it contained any characters or not.



来源:https://stackoverflow.com/questions/20915827/handle-empty-string-case-extracting-a-string-from-stdistream

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!