Блог пользователя CodingKnight

Автор CodingKnight, 6 лет назад, По-английски

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
}
  • Проголосовать: нравится
  • -23
  • Проголосовать: не нравится

»
6 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

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.

»
6 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

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

»
6 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

I prefer a static initializer, it is called before main(), example

const bool ready = [](){
    ios_base::sync_with_stdio(false); cin.tie(0);
    cout << fixed << setprecision(12);
    return true;
}();

signed main() {
  // no init call nessecary
}