Buffered reading from stdin using fread in C

前端 未结 11 1526
梦谈多话
梦谈多话 2020-12-24 03:36

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

11条回答
  •  离开以前
    2020-12-24 04:33

    I am going to recommend trying full buffering with setvbuf and ditching fread. If the specification is that there is one number per line, I will take that for granted, use fgets to read in a full line and pass it to strtoul parse the number that is supposed to be on that line.

    #include 
    #include 
    #include 
    #include 
    
    #define INITIAL_BUFFER_SIZE 2 /* for testing */
    
    int main(void) {
        int n;
        int divisor;
        int answer = 0;
        int current_buffer_size = INITIAL_BUFFER_SIZE;
        char *line = malloc(current_buffer_size);
    
        if ( line == NULL ) {
            return EXIT_FAILURE;
        }
    
        setvbuf(stdin, (char*)NULL, _IOFBF, 0);
    
        scanf("%d%d\n", &n, &divisor);
    
        while ( n > 0 ) {
            unsigned long dividend;
            char *endp;
            int offset = 0;
            while ( fgets(line + offset, current_buffer_size, stdin) ) {
                if ( line[strlen(line) - 1] == '\n' ) {
                    break;
                }
                else {
                    int new_buffer_size = 2 * current_buffer_size;
                    char *tmp = realloc(line, new_buffer_size);
                    if ( tmp ) {
                        line = tmp;
                        offset = current_buffer_size - 1;
                        current_buffer_size = new_buffer_size;
                    }
                    else {
                        break;
                    }
                }
            }
            errno = 0;
            dividend = strtoul(line, &endp, 10);
            if ( !( (endp == line) || errno ) ) {
                if ( dividend % divisor == 0 ) {
                    answer += 1;
                }
            }
            n -= 1;
        }
    
        printf("%d\n", answer);
        return 0;
    }
    

    I used a Perl script to generate 1,000,000 random integers between 0 and 1,000,000 and checked if they were divisible by 5 after compiling this program with gcc version 3.4.5 (mingw-vista special r3) on my Windows XP laptop. The whole thing took less than 0.8 seconds.

    When I turned buffering off using setvbuf(stdin, (char*)NULL, _IONBF, 0);, the time went up to about 15 seconds.

提交回复
热议问题