Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

reading formatted input using C++ streams

Tags:

c++

iostream

When using stdio.h, I can easily read certain kinds of formatted input like this:

FILE* fin = fopen(...);
fscanf(fin, "x = %d, y = %d", &x, &y);

The great thing about this is that I don't really have to worry about how many spaces there are between the character 'x' and the following '=', and other minor details.

In C++ it appears to me as though,

ifstream fin(...);
string s;
fin >> s;

may result in s being "x" or "x=", or even "x=12" depending on the spacing of the input.

Is there a convenient way to get behavior similar to scanf/fscanf using iostream/fstream?

like image 952
math4tots Avatar asked Jun 21 '13 20:06

math4tots


People also ask

What is formatted input output in C?

The C language comes with standard functions printf() and scanf() so that a programmer can perform formatted output and input in a program. The formatted functions basically present or accept the available data (input) in a specific format.

Which function is used to read a formatted stream string of text from a file?

The fscanf() function reads data from the current position of the specified stream into the locations that are given by the entries in argument-list, if any. Each entry in argument-list must be a pointer to a variable with a type that corresponds to a type specifier in format-string.

What is C++ streams explain formatted input output operations file system?

1.1 Streams C/C++ IO are based on streams, which are sequence of bytes flowing in and out of the programs (just like water and oil flowing through a pipe). In input operations, data bytes flow from an input source (such as keyboard, file, network or another program) into the program.


1 Answers

This is actually surprisingly easy, given a prerequisite. I have these three functions that I stick in a header somewhere. These allow you to stream in character literals, and string literals. I've never quite understood why these aren't standard.

#include <iostream>

//These are handy bits that go in a header somewhere
template<class e, class t, int N>
std::basic_istream<e,t>& operator>>(std::basic_istream<e,t>& in, const e(&sliteral)[N]) {
        e buffer[N-1] = {}; //get buffer
        in >> buffer[0]; //skips whitespace
        if (N>2)
                in.read(buffer+1, N-2); //read the rest
        if (strncmp(buffer, sliteral, N-1)) //if it failed
                in.setstate(std::ios::failbit); //set the state
        return in;
}
template<class e, class t>
std::basic_istream<e,t>& operator>>(std::basic_istream<e,t>& in, const e& cliteral) {
        e buffer(0);  //get buffer
        in >> buffer; //read data
        if (buffer != cliteral) //if it failed
                in.setstate(std::ios::failbit); //set the state
        return in;
}
//redirect mutable char arrays to their normal function
template<class e, class t, int N>
std::basic_istream<e,t>& operator>>(std::basic_istream<e,t>& in, e(&carray)[N]) {
        return std::operator>>(in, carray);
}

Given those, the rest is easy:

in>>'x'>>'='>>data.first>>','>>'y'>>'='>>data.second;

Proof here

For more complex situations, you probably want to use std::regex or boost::regex, or maybe a real lexer/parser.

like image 97
Mooing Duck Avatar answered Oct 02 '22 11:10

Mooing Duck