I am trying to efficiently read from the stdin
by using setvbuf
in `_IOFBF~ mode. I am new to buffering. I am looking for working examples.
The input begins with two integers (n
,k
). The next n
lines of input contain 1 integer. The aim is to print how many integers are divisible by k
.
#define BUFSIZE 32
int main(){
int n, k, tmp, ans=0, i, j;
char buf[BUFSIZE+1] = {'0'};
setvbuf(stdin, (char*)NULL, _IONBF, 0);
scanf("%d%d\n", &n, &k);
while(n>0 && fread(buf, (size_t)1, (size_t)BUFSIZE, stdin)){
i=0; j=0;
while(n>0 && sscanf(buf+j, "%d%n", &tmp, &i)){
//printf("tmp %d - scan %d\n",tmp,i); //for debugging
if(tmp%k==0) ++ans;
j += i; //increment the position where sscanf should read from
--n;
}
}
printf("%d", ans);
return 0;
}
The problem is if number is at the boundary, the buffer buf
will read 23
from 2354\n
, when it should have either read 2354
(which it cannot) or nothing at all.
How can I solve this issue?
Version 1 : Using getchar_unlocked
as suggested by R Samuel Klatchko (see comments)
#define BUFSIZE 32*1024
int main(){
int lines, number=0, dividend, ans=0;
char c;
setvbuf(stdin, (char*)NULL, _IOFBF, 0);// full buffering mode
scanf("%d%d\n", &lines, ÷nd);
while(lines>0){
c = getchar_unlocked();
//parse the number using characters
//each number is on a separate line
if(c=='\n'){
if(number % dividend == 0) ans += 1;
lines -= 1;
number = 0;
}
else
number = c - '0' + 10*number;
}
printf("%d are divisible by %d \n", ans, dividend);
return 0;
}
Version 2: Using fread
to read a block and parsing number from it.
#define BUFSIZE 32*1024
int main(){
int lines, number=0, dividend, ans=0, i, chars_read;
char buf[BUFSIZE+1] = {0}; //initialise all elements to 0
scanf("%d%d\n",&lines, ÷nd);
while((chars_read = fread(buf, 1, BUFSIZE, stdin)) > 0){
//read the chars from buf
for(i=0; i < chars_read; i++){
//parse the number using characters
//each number is on a separate line
if(buf[i] != '\n')
number = buf[i] - '0' + 10*number;
else{
if(number%dividend==0) ans += 1;
lines -= 1;
number = 0;
}
}
if(lines==0) break;
}
printf("%d are divisible by %d \n", ans, dividend);
return 0;
}
Results: (10 million numbers tested for divisibility by 11)
Run 1: ( Version 1 without setvbuf ) 0.782 secs
Run 2: ( Version 1 with setvbuf ) 0.684 secs
Run 3: ( Version 2 ) 0.534
P.S. - Every run compiled with GCC using -O1 flag