Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

stl

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.

like image 805
mpromonet Avatar asked Sep 01 '25 22:09

mpromonet


2 Answers

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;
}
like image 153
David G Avatar answered Sep 03 '25 13:09

David G


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.

like image 41
Lightness Races in Orbit Avatar answered Sep 03 '25 14:09

Lightness Races in Orbit