Hello Codeforces,
It is sometimes required in competetive programming problems to use fast data input/output and/or read and write problem data from and to data files. It is well known that the C++ standard libray functions std::ios_base::sync_with_stdio(), std::basic_io::tie(), and std::freopen() can be used to peform the sought input/output initializtion. The following is a C++ io_init
class that simplifies this initialization by encapsulating it inside public class constructors.
#include <bits/stdc++.h>
using namespace std;
class io_init {
struct fast { fast() { ios_base::sync_with_stdio(false), cin.tie(nullptr); } } io;
void reopen(const string &file_name, const char *mode, FILE *stream) {
if (freopen(file_name.c_str(),mode,stream) == nullptr)
throw runtime_error("freopen() failed: cannot open file "+file_name); }
public:
io_init() {}
io_init(const string &data) { reopen(data+".in","r",stdin), reopen(data+".out","w",stdout); } };
int main() {
io_init(); // io_init("data");
// solution
}
The first class constructor without parameter initializes fast input/output by creating the io
instance of the private data structure fast
. The second class constructor with string data
paremeter performs the same operation, and then initializes the data input/output to read data from input file data+".in"
and write results to output file data+".out"
. The private class member function reopen()
throws a run-time error exception if the freopen()
function call returns nullptr
.
Your constructive comments and feedback are welcome and appreciated.
UPDATE
The following alternative to use a fuction call instead of using public class constructors is favored by Actium.
#include <bits/stdc++.h>
using namespace std;
void io_init(const string &data = "") {
const auto reopen = [data](const string &ext, const char *mode, FILE *stream) {
const string file_name = data+"."+ext;
if (freopen(file_name.c_str(),mode,stream) == nullptr)
throw runtime_error("freopen() failed: cannot open file "+file_name); };
if (ios_base::sync_with_stdio(false), cin.tie(nullptr), not data.empty())
reopen("in","r",stdin), reopen("out","w",stdout); }
int main() {
io_init(); // io_init("data");
}
A third alterntative (favored by spookywooky) that does not require a function call to be included in the main()
function is to declare io_init
as a named lambda expression as follows.
#include <bits/stdc++.h>
using namespace std;
const auto io_init = [](const string &data = "") {
const auto reopen = [data](const string &ext, const char *mode, FILE *stream) {
const string file_name = data+"."+ext;
if (freopen(file_name.c_str(),mode,stream) == nullptr)
throw runtime_error("freopen() failed: cannot open file "+file_name); };
if (ios_base::sync_with_stdio(false), cin.tie(nullptr), not data.empty())
reopen("in","r",stdin), reopen("out","w",stdout);
return 0; } (); // ("data");
int main() {
// solution
}
A fourth alterntative and perhaps the simplest way to initialize data input/output files for read/write is to create std::ifsteam and std::ofstream objects. Names other than cin
and cout
should be used for the created object if using namespace std;
is part of the program so as to avoid name redeclaration errors.
#include <bits/stdc++.h>
using namespace std;
ifstream i_data("data.in");
ofstream o_data("data.out");
#define cin i_data
#define cout o_data
int main() {
int a, b;
cin >> a >> b; // read (a) and (b) from file data.in
cout << a+b << endl; // write (a+b) to file data.out
}