How to calculate the number of lines in a file?

I am working in C language for the first time and wondering.

How can I get the number of lines in a file?

FILE *in;
char c;
int lines = 1;
...
while (fscanf(in,"%c",&c)  == 1) {
  if (c == '\n') {
    lines++;
  }
}

      

I'm right? I don't really know how to get the moment when the line crosses the newline.

+3


source to share


3 answers


The OP code works well, except maybe the issue released separately and the last line issue.

C library standard definition

A text stream is an ordered sequence of characters arranged in lines, each line consisting of zero or more characters plus a terminating newline character. Whether the last line matches a trailing newline is implementation-defined. C11dr ยง7.21.2 2

The line ends with '\n'

, and the last line may or may not end with '\n

'.

If you are using the idea that no final is required for the last line of a file '\n

, then the goal is to count the number of occurrences that a character reads after '\n'

.



// Let us use a wide type
// Start at 0 as the file may be empty
unsigned long long line_count = 0;

int previous = '\n';
int ch;
while ((ch = fgetc(in)) != EOF) {
  if (previous == '\n') line_count++;
  previous = ch;
}

printf("Line count:%llu\n", line_count);

      


Reading a file one character at a time may be less efficient than other means, but functionally suits the OP's purpose.

This answer uses (ch = fgetc(in)) != EOF

instead fscanf(in,"%c",&c) == 1

, which is generally "faster", but with an optimizing compiler, or can generate similar performance code. Such speed details can be supported by analysis or profiling., Code for clarity.

+4


source


Can use this utility function



/*
* count the number of lines in the file called filename
*
*/
int countLines(char *filename)
{

  FILE *in = fopen(filename,"r");
  int ch=0;
  int lines=0;

  if(in == NULL){
     return 0; // return lines;
  }
  while((ch = fgetc(in)) != EOF){

     if(ch == '\n'){
        lines++;
     }
  }
    fclose(in);
  return lines;
}

      

0


source


When counting the number of characters \n

, you must remember that you are counting separators, not elements. See ' Fencepost error

Your example should work, but:

  • If the file doesn't end with \n

    , then you might be fine (depending on your definition of "string").
  • depending on your definition of "string" you may be missing \r

    characters in the file (typically used by Mac)
  • it won't be very efficient or fast (the call is scanf()

    expensive)

The example below will load the buffer each time, looking for characters \r

and \n

. There is some logic to latch these characters, so the following lines need to be handled correctly:

  • \n

  • \r

  • \r\n

#include <stdio.h>
#include <errno.h>

int main(void) {
    FILE *in;
    char buf[4096];
    int buf_len, buf_pos;
    int line_count, line_pos;
    int ignore_cr, ignore_lf;

    in = fopen("my_file.txt", "rb");
    if (in == NULL) {
        perror("fopen()");
        return 1;
    }

    line_count = 0;
    line_pos = 0;
    ignore_cr = 0;
    ignore_lf = 0;

    /* ingest a buffer at a time */
    while ((buf_len = fread(&buf, 1, sizeof(buf), in)) != 0) {

        /* walk through the buffer, looking for newlines */
        for (buf_pos = 0; buf_pos < buf_len; buf_pos++) {

            /* look for '\n' ... */
            if (buf[buf_pos] == '\n') {
                /* ... unless we've already seen '\r' */
                if (!ignore_lf) {
                    line_count += 1;
                    line_pos = 0;
                    ignore_cr = 1;
                }

            /* look for '\r' ... */
            } else if (buf[buf_pos] == '\r') {
                /* ... unless we've already seen '\n' */
                if (!ignore_cr) {
                    line_count += 1;
                    line_pos = 0;
                    ignore_lf = 1;
                }

            /* on any other character, count the characters per line */
            } else {
                line_pos += 1;
                ignore_lf = 0;
                ignore_cr = 0;
            }
        }
    }

    if (line_pos > 0) {
        line_count += 1;
    }

    fclose(in);

    printf("lines: %d\n", line_count);

    return 0;
}

      

0


source







All Articles