/* line_counter.c Written by Tanya Amert for Fall 2024 Prints out the count of lines in a file (and optionally also the length of each line). Compile as usual: gcc -Wall -Werror -g -o line_counter line_counter.c Run with one command-line argument, specifying a valid filename: ./line_counter myfile.txt */ #include // Change to 0 to turn off debugging print statements #define DEBUG 1 // Method declarations void print_usage_statement(const char *program_name); int get_line_count(const char *file_name); // Counts the number of lines in a file specified // as a command-line argument; prints the results to // standard output int main(int argc, char *argv[]) { // Check that we have enough command-line arguments if (argc != 2) { print_usage_statement(argv[0]); return 1; // anything other than 0 indicates failure } // Parse the command-line argument for the filename const char *input_file_name = argv[1]; // Do the work int line_count = get_line_count(input_file_name); if (line_count < 0) { fprintf(stderr, "Trouble counting the lines in %s\n", input_file_name); return 1; // another failure case } printf("Number of lines: %d (0x%x)\n", line_count, line_count); return 0; } // Prints information for how to use this program. void print_usage_statement(const char *program_name) { fprintf(stderr, "Usage: %s inputfile\n", program_name); fprintf(stderr, " prints to standard output the number of lines\n"); fprintf(stderr, " (as a decimal integer) in the specified file\n"); } // Returns the number of lines in the specified file, or -1 if an error // occurs. Errors include failure to open or read from the file. // // If debugging print statements are enabled, also prints // the length of each line and its first character (counts line // numbers starting at 0). // // Assumes the last line does not end in '\n'. int get_line_count(const char *file_name) { // Open the file for reading FILE *input_file = fopen(file_name, "r"); if (input_file == NULL) { return -1; } // Keep track of the current line number, how long it is, and what // the character before the previous one was (just use '\n' at the start) int current_line = 0; int current_length = 0; char prev = '\n'; // Loop through the file one char/byte at a time, counting lines as we go char ch = fgetc(input_file); while (ch != EOF) { // Check if we found a newline character if (ch == '\n') { // If we're debugging, print out the length of this line if (DEBUG) { printf("Line %d has length: %d\n", current_line, current_length); } // Get ready for the next line current_line++; current_length = 0; } // If not, maybe this is the start of a new line else if (prev == '\n') { // Update the count current_length++; // If we're debugging, print out the first character of this line if (DEBUG) { printf("\nLine %d starts with: '%c'\n", current_line, ch); } } // Otherwise, just update the count else { current_length++; } // Store this character and read the next one prev = ch; ch = fgetc(input_file); } // If ferror returns true, we hit EOF because of some issue, so fail out if (ferror(input_file)) { fclose(input_file); return -1; } // We assume the last line doesn't end in \n (not always true), // so by hitting EOF we finally saw its end if (DEBUG) { printf("Line %d has length: %d\n", current_line, current_length); } // Clean up after ourselves fclose(input_file); // Return the line count +1 as the number of lines we saw return current_line + 1; }