Open-Source Internship opportunity by OpenGenus for programmers. Apply now.
In this article, we have presented how to optimize input and output I/O in C++. This is critical as input and output consume the majority of the execution time and is critical in time critical applications and in competitive programming contests.
Table of contents:
- Fastest I/O functions
- Use ios_base::sync_with_stdio
- cin and cout
- Avoid use of endl
- Conclusion
Fastest I/O functions
There are several I/O functions in C and C++ such as printf, scanf, write, fwrite, cout, cin, read, fread putchar and much more.
Following is the ordered list of I/O functions dealing with integers in ascending order (faster to slowest):
- printf (fastest for integer)
- scanf
- write
- fwrite
- cout
- cin (slowest for integer)
Following is the ordered list of I/O functions dealing with characters/ strings in ascending order (faster to slowest):
- read (fastest for character)
- fread
- printf
- getchar
- putchar
- cout
- scanf
- cin (slowest for character)
The straight conclusion is:
- For integer input, use scanf and for character input, use read.
- For both integer and character output, use printf.
This is true for most standard systems. To test the order for your own system, use the following C++ program which we used to benchmark the different I/O functions:
// Benchmark to test I/O functions in C++
// Part of iq.opengenus.org
#include <iostream>
#include <string>
#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <iomanip>
#include <cctype>
using namespace std;
const int N=10000000,NC=10*N;
int a[N],swtime,swsize;
char s[NC];
char sw[16*N];
void gen() {
for (int i=0;i<N;i++) {
a[i]=rand();
}
for (int i=0;i<NC;i++) {
s[i]=rand()%10+'0';
}
int cur=clock();
swsize=0;
for (int i=0;i<N;i++) {
char s[100];
sprintf(s,"%d",a[i]);
for (int j=0;s[j];j++) {
sw[swsize++]=s[j];
}
sw[swsize++]=' ';
}
swtime=clock()-cur;
}
void test_printf_int() {
int cur=clock();
freopen("temp.txt","w",stdout);
for (int i=0;i<N;i++)
printf("%d ",a[i]);
fclose(stdout);
fprintf(stderr,"Test: (printf, %d ints) %.2lfc\n",N,(clock()-cur+.0)/CLOCKS_PER_SEC);
}
void test_cout_int() {
int cur=clock();
freopen("temp.txt","w",stdout);
for (int i=0;i<N;i++)
cout << a[i] << ' ';
fclose(stdout);
fprintf(stderr,"Test: (cout, %d ints) %.2lfc\n",N,(clock()-cur+.0)/CLOCKS_PER_SEC);
}
void test_write_int() {
int cur=clock();
freopen("temp.txt","w",stdout);
cout.write(sw,swsize);
fclose(stdout);
fprintf(stderr,"Test: (write, %d ints, %d chars) %.2lfc + %.2lfc\n",N,swsize,(swtime+.0)/CLOCKS_PER_SEC,(clock()-cur+.0)/CLOCKS_PER_SEC);
}
void test_fwrite_int() {
int cur=clock();
freopen("temp.txt","w",stdout);
fwrite(sw,1,swsize,stdout);
fclose(stdout);
fprintf(stderr,"Test: (fwrite, %d ints, %d chars) %.2lfc + %.2lfc\n",N,swsize,(swtime+.0)/CLOCKS_PER_SEC,(clock()-cur+.0)/CLOCKS_PER_SEC);
}
void test_scanf_int() {
int cur=clock();
freopen("temp.txt","r",stdin);
for (int i=0;i<N;i++) {
int t;
scanf("%d",&t);
if (t!=a[i]) {
fprintf(stderr,"Fail with scanf\n");
exit(1);
}
}
fclose(stdin);
fprintf(stderr,"Test: (scanf, %d ints) %.2lfc\n",N,(clock()-cur+.0)/CLOCKS_PER_SEC);
}
// Part of iq.opengenus.org
void test_cin_int() {
int cur=clock();
freopen("temp.txt","r",stdin);
for (int i=0;i<N;i++) {
int t;
cin >> t;
if (t!=a[i]) {
fprintf(stderr,"Fail with cin\n");
exit(1);
}
}
fclose(stdin);
fprintf(stderr,"Test: (cin, %d ints) %.2lfc\n",N,(clock()-cur+.0)/CLOCKS_PER_SEC);
}
void test_printf_char() {
int cur=clock();
freopen("temp.txt","w",stdout);
for (int i=0;i<NC;i++)
printf("%c",s[i]);
fclose(stdout);
fprintf(stderr,"Test: (printf, %d chars) %.2lfc\n",NC,(clock()-cur+.0)/CLOCKS_PER_SEC);
}
void test_cout_char() {
int cur=clock();
freopen("temp.txt","w",stdout);
for (int i=0;i<NC;i++)
cout << s[i];
fclose(stdout);
fprintf(stderr,"Test: (cout, %d chars) %.2lfc\n",NC,(clock()-cur+.0)/CLOCKS_PER_SEC);
}
void test_putchar_char() {
int cur=clock();
freopen("temp.txt","w",stdout);
for (int i=0;i<NC;i++)
putchar(s[i]);
fclose(stdout);
fprintf(stderr,"Test: (putchar, %d chars) %.2lfc\n",NC,(clock()-cur+.0)/CLOCKS_PER_SEC);
}
void test_scanf_char() {
int cur=clock();
freopen("temp.txt","r",stdin);
for (int i=0;i<NC;i++) {
char t;
scanf("%c",&t);
if (t!=s[i]) {
fprintf(stderr,"Fail with scanf\n");
exit(1);
}
}
fclose(stdin);
fprintf(stderr,"Test: (scanf, %d chars) %.2lfc\n",NC,(clock()-cur+.0)/CLOCKS_PER_SEC);
}
void test_cin_char() {
int cur=clock();
freopen("temp.txt","r",stdin);
for (int i=0;i<NC;i++) {
char t;
cin >> t;
if (t!=s[i]) {
fprintf(stderr,"Fail with cin\n");
exit(1);
}
}
fclose(stdin);
fprintf(stderr,"Test: (cin, %d chars) %.2lfc\n",NC,(clock()-cur+.0)/CLOCKS_PER_SEC);
}
void test_getchar_char() {
int cur=clock();
freopen("temp.txt","r",stdin);
for (int i=0;i<NC;i++) {
char t=getchar();
if (t!=s[i]) {
fprintf(stderr,"Fail with getchar\n");
exit(1);
}
}
fclose(stdin);
fprintf(stderr,"Test: (getchar, %d chars) %.2lfc\n",NC,(clock()-cur+.0)/CLOCKS_PER_SEC);
}
void test_read_char() {
int cur=clock();
freopen("temp.txt","r",stdin);
cin.read(sw,NC);
fclose(stdin);
int cur2=clock();
for (int i=0;i<NC;i++)
if (s[i]!=sw[i]) {
cerr << i << ' ' << (int)s[i] << ' ' << (int)sw[i] << endl;
fprintf(stderr,"Fail with read\n");
exit(1);
}
fprintf(stderr,"Test: (read, %d chars) %.2lfc + %.2lfc\n",NC,(cur2-cur+.0)/CLOCKS_PER_SEC,(clock()-cur2+.0)/CLOCKS_PER_SEC);
}
void test_fread_char() {
int cur=clock();
freopen("temp.txt","r",stdin);
fread(sw,1,NC,stdin);
fclose(stdin);
int cur2=clock();
for (int i=0;i<NC;i++)
if (s[i]!=sw[i]) {
fprintf(stderr,"Fail with fread\n");
exit(1);
}
fprintf(stderr,"Test: (fread, %d chars) %.2lfc + %.2lfc\n",NC,(cur2-cur+.0)/CLOCKS_PER_SEC,(clock()-cur2+.0)/CLOCKS_PER_SEC);
}
int main () {
gen();
test_printf_int();
test_cout_int();
test_write_int();
test_scanf_int();
test_fwrite_int();
test_cin_int();
test_printf_char();
test_scanf_char();
test_cout_char();
test_cin_char();
test_putchar_char();
test_getchar_char();
test_read_char();
test_fread_char();
}
Use ios_base::sync_with_stdio
Add the following code line at the top of your C++ program:
ios_base::sync_with_stdio(false);
This allows the interleaving between iostream and stdio functions and use the same stream. This enables iostream to work efficiently.
cin and cout
cin and cout are the slowest I/O functions so should be avoided. If used, add the following code line:
cin.tie(NULL);
This allows cout to be untied from cin. This results in cout being flushed before cin. In interactive programs, this should be avoided and flush should be added after each cin and cout.
Avoid use of endl
Avoid use of endl.
This is because when endl is used it outputs a new line after flushing the stream buffer which is an expensive operation. Use "\n" instead of endl.
Conclusion
The conclusion is:
- For integer input, use scanf and for character input, use read.
- For both integer and character output, use printf.
- Add ios_base::sync_with_stdio(false); in your code.
- Add cin.tie(NULL); in your code.
- Use "\n" instead of endl.
With this article at OpenGenus, you must have the complete idea of how to optimize input and output I/O functions in C++.