patterncMinor
C program to count number of lines in a file
Viewed 0 times
numberfileprogramcountlines
Problem
Very simple code, works fine. I'm mainly interested in the method I used to count lines. I thought about using fgetc, but I'm not even sure if it'd read the newline character, and I think it's slower too.
#include
#include
#define MAX_SIZE 1000
int main(void){
FILE *in_file;
char line[MAX_SIZE];
in_file = fopen("test", "r");
if(in_file == NULL){
fprintf(stderr, "Unable to open file");
exit(EXIT_FAILURE);
}
int counter = 0; /*Number of lines*/
while(fgets(line, sizeof(line), in_file) != NULL){
counter++;
}
printf("Number of lines in the file is %i", counter);
return 0;
}Solution
As you say, it works fine. But I can nitpick.
The main flaw is that you could get a wrong count if any line is longer than 999 bytes. (In general, you should stress-test your code by cranking down the buffer size to ridiculously small numbers and checking whether you obtain the same results.)
The performance could be improved. Since
It's awkward to read 1000 bytes at a time. You would be better off reading chunks that are aligned with the blocks on the disk. A better choice would be 1024.
You could use the
It's a good habit to ensure that your
The
means:
The extra set of parentheses around
The main flaw is that you could get a wrong count if any line is longer than 999 bytes. (In general, you should stress-test your code by cranking down the buffer size to ridiculously small numbers and checking whether you obtain the same results.)
The performance could be improved. Since
fgets() has no way of knowing in advance where the newlines occur, it must read the file contents into a temporary buffer (which is invisible to you), then copy each line into the line buffer. Since only care about counting '\n' characters, you could read fixed-size blocks to avoid this internal copying.It's awkward to read 1000 bytes at a time. You would be better off reading chunks that are aligned with the blocks on the disk. A better choice would be 1024.
You could use the
perror() function to report why I/O operations failed. Technically, fgets() could fail too, so you should check for that.It's a good habit to ensure that your
fopen() is paired with fclose().#include
#include
#include
#define SIZE 1024
int main(void) {
const char filename[] = "test";
FILE *in_file;
char buffer[SIZE + 1], lastchar = '\n';
size_t bytes;
int lines = 0;
if (NULL == (in_file = fopen(filename, "r"))) {
perror(filename);
return EXIT_FAILURE;
}
while ((bytes = fread(buffer, 1, sizeof(buffer) - 1, in_file))) {
lastchar = buffer[bytes - 1];
for (char *c = buffer; (c = memchr(c, '\n', bytes - (c - buffer))); c++) {
lines++;
}
}
if (lastchar != '\n') {
lines++; /* Count the last line even if it lacks a newline */
}
if (ferror(in_file)) {
perror(filename);
fclose(in_file);
return EXIT_FAILURE;
}
fclose(in_file);
printf("Number of lines in the file is %i\n", lines);
}The
for loop above is a bit tricky for beginners, but should be acceptable for experienced C programmers. The loopfor (char *c = buffer; (c = memchr(c, '\n', bytes - (c - buffer))); c++)means:
- Search for the next newline, starting from the pointer
c, in the remainingbytes - (c - buffer)bytes that have been read but not examined yet.
- If a newline is found, make
cpoint to the position just after it.
- If no newline is found, then we're done with this chunk. Try reading more input then.
The extra set of parentheses around
c = memchr(…) is an indication to the compiler and to other programmers that the = is indeed intentional, and is not supposed to be ==.Code Snippets
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 1024
int main(void) {
const char filename[] = "test";
FILE *in_file;
char buffer[SIZE + 1], lastchar = '\n';
size_t bytes;
int lines = 0;
if (NULL == (in_file = fopen(filename, "r"))) {
perror(filename);
return EXIT_FAILURE;
}
while ((bytes = fread(buffer, 1, sizeof(buffer) - 1, in_file))) {
lastchar = buffer[bytes - 1];
for (char *c = buffer; (c = memchr(c, '\n', bytes - (c - buffer))); c++) {
lines++;
}
}
if (lastchar != '\n') {
lines++; /* Count the last line even if it lacks a newline */
}
if (ferror(in_file)) {
perror(filename);
fclose(in_file);
return EXIT_FAILURE;
}
fclose(in_file);
printf("Number of lines in the file is %i\n", lines);
}for (char *c = buffer; (c = memchr(c, '\n', bytes - (c - buffer))); c++)Context
StackExchange Code Review Q#156477, answer score: 7
Revisions (0)
No revisions yet.