Sharpbombs Sharpbombs - 1 month ago 18
C Question

Segmentation Fault on my while loop

I am trying to count the number of lines and characters whatever they may be in a file that I specify from argv. But I get a segmentation fault when I hit the while loop for some reason. The program runs fine without the while loop, though it only goes through once.

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

int main(int argc, char *argv[]) {

if(argc != 2) {
return 0;
}


FILE *fp;
char c;
int lines = 0;
int chs = 0;
fp = fopen(argv[1], "r");

//Segmentation Fault happens here on the while loop
while((c = fgetc(fp)) != EOF) {
if(c == '\n') {
lines += 1;
}
else {
chs += 1;
}

}

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


if(fp){
fclose(fp);
}
return 0;
}

Dai Dai
Answer
  • Your code needs to be follow Idiomatic C more closely.
  • You should validate fopen immediately, instead of after you've already attempted to use fp.
  • fgetc returns int, not char. This is because it needs to return side-channel information about the status of the stream (i.e. EOF), this information cannot be represented by char, but you can safely cast the int value to char if the value is not EOF.
  • Your code treats \r as a regular character when it is commonplace for \r\n to represent a line-break (not just a solitary \n), you might want to consider how you handle different character classes.
  • Your program does not handle non-trivial encodings (i.e. it will only correctly handle files in your system's native encoding, presumably ASCII). You should use a Unicode library to correctly read individual characters from a file: for example your program will treat a surrogate-pair in UTF-8 as two characters instead of 1, and would incorrectly count UTF-16 files.

Better:

FILE* fp = fopen( argv[1], "r" );
if( !fp ) {
    printf( "Could not open file \"%s\" for reading.\r\n", argv[1] );
    return 1;
}

int lines = 0;
int chars = 0;

int nc;
while( ( nc = fgetc( fp ) ) != EOF ) {

    char c = (char)nc;

    if     ( c == '\n' ) lines++;
    else if( c != '\r' ) chars++;
}

printf( "Characters: %d\r\nLines: %d\r\n", chars, lines );

fclose( fp );

return 0;
Comments