Search code examples
cperformancefileline

C - Efficient way to get amount of lines of a text file


I just found this thread with the same question but in C#.
How do you achieve this in C? Is there a better solution than using a loop until it reaches EOF like this or is there already a function in the libs which can do this?

#include <stdio.h>
#include <stdlib.h>

// ----- Macros -----
#define PATHSIZE 255
#define BUFFERPATHSIZE PATHSIZE + 1

// ----- Functions -----
short get_amount_of_lines_of_file(char * path);

// -----======##### CODDE #####=====-----
int main() {

    char buffer[PATHSIZE];
    fgets(buffer, BUFFERPATHSIZE, stdin);

    printf("%d\n", get_amount_of_lines_of_file(buffer));

    return EXIT_SUCCESS;
}

short get_amount_of_lines_of_file(char * path) {
    /*
     * This will return the amount of lines of a file.
     * ----- Variables -----
     * lines: The counter of the lines
     * 
     * ----- Return -----
     * -1: Couldn't open file
     * lines: The amount of lines 
     */

    FILE *file;
    int rofl;
    short lines = 0;

    if ((file = fopen(path, "r")) != NULL) {

        while ((rofl = getc(file)) != EOF) 
            lines++;

        return lines;
    }

    return EXIT_FAILURE;
}

Solution

  • if you want to be fast, and if your memory is large enough, you can read in the entire file, and parse to to get the newline counts, try this: compile with gcc -g wc1.c -O3 -o wc1:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #ifdef __OSX__
       #define NLINE '\r'
    #else
       #define NLINE '\n'
    #endif
    void main(int argn, char **argv){
      if(argn<2) return;
      FILE *fp=fopen(argv[1],"rb");
      int count=0;
      size_t flen;
      char *nb,*body;
    
      fseek(fp,0,SEEK_END);
      flen=ftell(fp);
      body=(char*)calloc(1,flen+1);
      fseek(fp,0,SEEK_SET);
      if(fread(body,flen,1,fp)!=1){
        fclose(fp);
        exit(-1);
      }
      fclose(fp);
      nb=body;
      while(nb=strchr(nb,NLINE)){
          count++;
          nb++;
      }
      free(body);
      printf("filename %s: line count %d\n",argv[1],count);
    }
    

    alternatively, you can also set a maximum line width and call fgets to read line by line, try this: gcc -g wc2.c -O3 -o wc2

    #include <stdio.h>
    #define MAX_LINE_LENGTH 4096
    
    void main(int argn, char **argv){
      if(argn<2) return;
      FILE *fp=fopen(argv[1],"rt");
      int count=0;
      char line[MAX_LINE_LENGTH];
      while(!feof(fp)){
          if(fgets(line,MAX_LINE_LENGTH,fp))
             count++;
      }
      fclose(fp);
      printf("filename %s: line count %d\n",argv[1],count);
    }