我试图stdin
通过setvbuf
在`_IOFBF~模式下使用来有效地读取.我是新来的缓冲.我正在寻找有用的例子.
输入以两个整数(n
,k
)开头.下一n
行输入包含1个整数.目的是打印可以整除的整数数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;
}
Run Code Online (Sandbox Code Playgroud)
问题是如果数为界,缓冲区 buf
将读取23
距离2354\n
,当它应该已经读过2354
(它不能),或者什么都没有.
我该如何解决这个问题?
编辑
现已解决(带分析).
编辑
完整的问题规范
版本 1:getchar_unlocked
按照 R Samuel Klatchko 的建议使用(参见评论)
#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;
}
Run Code Online (Sandbox Code Playgroud)
版本 2:用于fread
读取块并从中解析数字。
#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;
}
Run Code Online (Sandbox Code Playgroud)
结果:(测试 1000 万个数字能否被 11 整除)
运行 1:(不带 setvbuf 的版本 1)0.782 秒
运行 2:(带 setvbuf 的版本 1)0.684 秒
运行 3:(版本 2)0.534
PS - 每次运行都使用 -O1 标志用 GCC 编译