fast I/O in C/C++
There many ways to do input/output in C/C++. Some are slow, some are fast and some can be very fast. Here I’ll be discussing some of these methods.
Many a times during competetive programming you come across the warning “Careful – large input/output“. Now what exactly does this means?
This basically means that you have to use an optimized code for your reading/writing to the standard input/output to stay inside the tighter time constraints of the problem. So let’s get going and explore the different methods to optimize your I/O in C/C++.
All the code can be found here: GitHub.
First one is the basic method that you guys must already be using. This is based on cin/cout methods of the iostream library. It is the most basic method and does not require you to specify the type of input you are expecting, but, is extremely slow.
#include <iostream> #include <string> #include <sstream> using namespace std; int main() { /* integer or any integer like */ int integer; cin>>integer; cout<<integer<<endl; /* character string */ char charstring[100]; cin>>charstring; // stops input after a "space" cout<<charstring<<endl; cin.getline(charstring, 100); // stops after 100 character or eof whichever comes first cout<<charstring<<endl; string strstring; cin>>strstring; // stops input after a "space" cout<<strstring<<endl; getline(cin, strstring); // stops after eof or '\n', whichever comes first cout<<strstring<<endl; /* safest way to get an integer (but very slow) - taken from cpluspls.com */ int number = 0; string input; while(true) { getline(cin, input); stringstream myStream(input); if(myStream>>number) break; } /* Safest way to get a single character */ char singlechar = {0}; while(true) { getline(cin, input); if(input.length() == 1){ singlechar = input[0]; break; } } }
The second method is based on the simple printf/scanf functions of stdio.h library for C. These are much faster than the above method and can be easily used in competetive programming for a decent time limit. These are multi-thread safe as they lock the file before writing.
Detailed description of the stdio.h library you can refer to here.
#include <cstdio> #include <string> int main() { /* integer I/O */ int a; scanf("%d", &a); printf("%d\n", a); /* Other format specifiers. %d, %i = signed integer %u = unsigned integer %l = prefix for long %f = signed floating point %e = signed scientific %c = single character */ /* sting I/O */ char charstring[100]; scanf("%s", charstring); // only till the first white space is stored printf("%s\n", charstring); scanf("%[^\n]s", charstring); // sets th delimeter to be "new line" printf("%s\n", charstring); // thus whole line is read until a \n is observed // does not eliminate \n from the input stream gets(charstring); printf("%s\n", charstring); }
This method is very fast than the last method and used unlocked versions of the above functions used. I have written the code to scan integer and a string. For others you can easily write your function referring the below code. These are NOT multi-thread safe. Should be used in caution. But, in competetive programming plateforms, one program is already separated from others, so can easilt be used for better I/O in competetive programming which have even tighter time constraints.
#include <cstdio> inline void fastRead_int(int &x) { register int c = getchar_unlocked(); x = 0; int neg = 0; for(; ((c<48 || c>57) && c != '-'); c = getchar_unlocked()); if(c=='-') { neg = 1; c = getchar_unlocked(); } for(; c>47 && c<58 ; c = getchar_unlocked()) { x = (x<<1) + (x<<3) + c - 48; } if(neg) x = -x; } inline void fastRead_string(char *str) { register char c = 0; register int i = 0; while (c < 33) c = getchar_unlocked(); while (c != '\n') { str[i] = c; c = getchar_unlocked(); i = i + 1; } str[i] = '\0'; } int main() { int n; char s[100]; fastRead_int(n); printf("%d\n", n); fastRead_string(s); printf("%s\n", s); return 0; }
There is another method I came across a solution in one of the problems on codechef. I haven’t tested it’s performance, but, his solution had the lowest timing with the same logic for the actual problem. So, I am assuming this gives a better performance for I/O. You can download the code here.
The solution referrenced is this.
I’ll come up with more updates on the same topic.
Hi, what’s the point of doing bitwise shift here: x = (x<<1) + (x<<3) + c – 48;
x=x*2^1+x*2^3+c-48…
Now you can understand what it does.
It multiplies the current value with 10 and then add the incoming character.
lets say x=0,c=’5′;
x=0+0+53-48;
x=5;
now c=’6′;
x=5*(2^1)+5*(2^3)+54-48;
=10+40+54-48—>56;
This is multiplying by 10
x = x * 10 + c
Hey Chirag,
Great site you got here. I’m not too familiar with C++ but thank you for providing the source to this fix. I also check out GitHub when I’m stuck.
Thanks for the resource.
Dennis
Thanks so much for the blog post. Awesome.
Which header file to include ?
The required header files are given in the code itself.
For the first one you need: iostream , string and sstream
second part: cstdio and string
For the third code you only need: cstdio
Thank you, btw awesome post. Great help.