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
}
I think it is enough to have a single function and call it from main(), that is class io_init + nested class fast are just overcomplication in my opinion.
Thanks for your feedback. I appreciate your opinion. Note that the class constructor can be called from the main() function just like any other function if it not necessary to store the object reference explicitly using a variable name. Check the updated main() function for an illustration.
Even object construction looks as a function call ;) Just make it a function that takes single argument (filename) with default value and does all the initialization work.
Check the update section. It does seem that the function call is simpler and more favored. It is even less by one line than the class implementation :-) Thanks again for your constructive feedback.
" throw runtime_error("freopen() failed: cannot open file "+file_name); }; " for this line, even for a hello world it is signalling : "[Error] 'runtime_error' was not declared in this scope"...
You have to add
#include <stdexcept>
std::runtime_error is a standard C++ class. Just use
#include <bits/stdc++.h>
in case that#include <iostream>
does not automatically include the C++ error handling library.I prefer a static initializer, it is called before main(), example
Thanks for your feedback. I have just added this third alternative to the update section before reading your comment.