1

I have a very simple scenario that looks like

std::ifstream file("myfile.txt");
std::string discard;
int num;
file >> discard >> num;  // to consume e.g. HEADER 55

Despite all of its other foibles, fscanf has a feature that is useful to me and I don't see obviously being available in ifstream. Quoting cppreference,

The format string consists of non-whitespace multibyte characters except %: each such character in the format string consumes exactly one identical character from the input stream, or causes the function to fail if the next character on the stream does not compare equal.

Other than >> to a string, comparing to a known value and aborting the operation if the comparison fails, is there something akin to a >> std::expect("HEADER") that would more directly express this case? (In my imagination this is "not so crazy" because other >> input operations already do this on other failure types such as integer parse failure).

7
  • Have you considered using a parser, like Boost Parser?
    – Eljay
    Commented Jun 30 at 19:11
  • @Eljay that's quite interesting, and I will read about it; but given that I don't currently rely on Boost and my parsing needs are pretty simple I would find it difficult to justify incorporating that dependency.
    – avigt
    Commented Jun 30 at 19:20
  • You could go for a serialization library - or write a small one yourself if there aren't that many types that you need deserializing.
    – Ted Lyngmo
    Commented Jun 30 at 19:47
  • @TedLyngmo But avoid binary serialization, there be Dragons. Commented Jul 1 at 4:57
  • Instead of re-inventing your own text format, use a library like nlohman/json and just read your input from a json file (or similarly there are libraries for yaml/xml etc.) Commented Jul 1 at 4:58

1 Answer 1

7

Other than >> to a string, comparing to a known value and aborting the operation if the comparison fails, is there something akin to a >> std::expect("HEADER") that would more directly express this case?

There is nothing native in the standard library for that exact purpose, but you can easily write your own I/O manipulator to handle it, eg:

class expect_t {
public:
    expect_t(const std::string_view &value) : m_value(value) {}

    friend std::istream& operator>>(std::istream &is, const expect_t &expected) {
        std::string s;
        if (is >> s) {
            if (expected.m_value != s) {
                is.setstate(std::ios_base::failbit);
            }
        }
        return is;
    }

private:
    std::string_view m_value;
};

expect_t expect(const std::string_view &value) { return expect_t{value}; }

Then you can do this:

std::ifstream file("myfile.txt");
int num;
if (file >> expect("HEADER") >> num) {  // to consume e.g. HEADER 55
    // OK, use num as needed...
} else {
    // failed
}

Demo

2
  • Is it possible that m_value may be made a string view?
    – avigt
    Commented Jul 2 at 18:25
  • 1
    Sure, you can use a std::string_view instead. I have updated my example to show this. Commented Jul 2 at 18:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.