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.
source to share
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.
source to share
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;
}
source to share
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;
}
source to share