Home > OS >  how to print line numbers from multiple files without using fgets
how to print line numbers from multiple files without using fgets

Time:12-06

enter image description hereI'm trying to print line numbers in the beginning of the lines without using fgets() yes, it prints line number well when I input multiple files but I want to get result like this. Can you guys help me with this?

Now result

1 I'll always remember
2 the day we kiss my lips
3
4 light as a feather
*5 ####@localhost ~ $*

expect result

1 I'll always remember
2 the day we kiss my lips
3
4 light as a feather
*####@localhost ~$*

Here is my code:

#include <stdio.h>

int main(int argc, char *argv[]) {
    FILE *fp;
    int c, n;
    n = 1;
    for (int i = 1; i < argc; i  ) {
        if (argc < 2) 
            fp = stdin; 
        else
            fp = fopen(argv[i], "r"); 
        c = getc(fp); 
        printf("%d ", n);
        while (c != EOF) { 
            putc(c, stdout); 
            if (c == '\n')
                n  , printf("%d ", n);
            c = getc(fp);
        }
        fclose(fp);
    }
    return 0;
}

CodePudding user response:

Do not write printf("%d ", n); when you do not know if there is the next line. Or, otherwise, do printf("%d ", n); only on the beginning of the file and after a newline when you know there is a next char.

#include <stdbool.h>  // for bool, true, false
  

  bool previous_character_was_a_newline = true;
  while ((c = getc(fp)) != EOF) { 
     if (previous_character_was_a_newline) {
          previous_character_was_a_newline = false;
          printf("%d ", n);
     }
     putc(c, stdout); 
     if (c == '\n') {
        n  ;
        previous_character_was_a_newline = true;
     }
  }

Do not write code like n , printf("%d ", n);, it will be confusing. Strongly prefer:

     if (c == '\n') {
        n  ;
        printf("%d ", n);
     }

CodePudding user response:

Your implementation outputs the line number before the first line and after each newline, including the one at the end of the file. This causes an extra line number to appear at the end of the file.

Let's define the output more precisely:

  • you want the line number at the beginning of each line, no output if no line, no line number after the last line.
  • do you want the line counter to reset to 1 when a new file is read? I assume no, but cat -n does.
  • do you want to output an extra newline at the end of a non empty file that does not end with a newline? I assume yes but cat -n does not.

Here is a modified version where the answer is no for the first question and yes for the second:

#include <stdio.h>

int output_file(FILE *fp, int line) {
    int c, last = '\n';
    while ((c = getc(fp)) != EOF) {
        if (last == '\n') {
            printf("%d\t", line  );
        }
        putchar(c);
        last = c;
    }
    /* output newline at end of file if non empty and no trailing newline */
    if (last != '\n') {
        putchar('\n');
    }
    return line;
}

int main(int argc, char *argv[]) {
    int n = 1;

    if (argc < 2) {
        n = output_file(stdin, n);
    } else {
        for (int i = 1; i < argc; i  ) {
            FILE *fp = fopen(argv[i], "r");
            if (fp == NULL) {
                perror(argv[i]);
            } else {
                n = output_file(fp, n);
                fclose(fp);
            }
        }
    }
    return 0;
}
  • Related