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? 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. 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. 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

Sign up to request clarification or add additional context in comments.

2 Comments

Is it possible that m_value may be made a string view?
Sure, you can use a std::string_view instead. I have updated my example to show this.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.