Is there a way to count the number of lines in my file using C?
One nagging issue that can effect the number of lines returned regardless of the method you use is whether the file contains a POSIX compliant '\n'
at the end of the last line. There are a number of editors (and programs) that happily write the final amount of text to a file without the POSIX end-of-line. You can handle either case regardless of which method you use to determine the number of lines in a file.
If you are trying to determine the number of line in a large file, then you will definitely want a buffered read (e.g. reading multiple characters into a buffer, per-read) rather than a character-by-character approach. The can greatly improve the efficiency.
Putting those two pieces together, you can use either fgets
or POSIX getline
to determine the number of lines in a file fairly efficiently. For example with getline
(which handles the line-end issue or you), you could do:
/** open and read each line in 'fn' returning the number of lines */
size_t nlinesgl (char *fn)
{
if (!fn) return 0;
size_t lines = 0, n = 0;
char *buf = NULL;
FILE *fp = fopen (fn, "r");
if (!fp) return 0;
while (getline (&buf, &n, fp) != -1) lines++;
fclose (fp);
free (buf);
return lines;
}
With fgets
, testing for additional text after the final newline is up to you, e.g.
/** note; when reading with fgets, you must allow multiple reads until
* '\n' is encountered, but you must protect against a non-POSIX line
* end with no '\n' or your count will be short by 1-line. the 'noeol'
* flag accounts for text without a '\n' as the last line in the file.
*/
size_t nlines (char *fn)
{
if (!fn) return 0;
size_t n = 0, noeol = 0;
char buf[FILENAME_MAX] = "";
FILE *fp = fopen (fn, "r");
if (!fp) return 0;
while (fgets (buf, FILENAME_MAX, fp)) {
noeol = 0;
if (!strchr (buf, '\n')) {
noeol = 1; /* noeol flag for last line */
continue;
}
n++;
}
if (noeol) n++; /* check if noeol, add 1 */
fclose (fp);
return n;
}
(note: you can add your own code to handle a fopen
failure in each function.)