0

Let's say I want to read a file where each line has a string, and when there is a new line or the end of the file, I print the number of characters read. For example,

abcdf
asd

sdfsd
aa

This would print (counting new line characters at the end of each string):

10
8

(there is no new line at the end of the last line, so we get 8 instead of 9). I could do something like this

FILE* f;
// ...
int charCount = 0;
char line[20];
while (fgets(line, sizeof line, f))
{
    if (strcmp(line, "\n") == 0)
    {
        printf("%d\n", charCount);
        charCount = 0;
    }
    else
    {
        charCount += strlen(line);
    }
}
printf("%d\n", charCount);

Notice that I have to repeat the printf after the loop ends, because if I don't, I wouldn't print the last value (because the file reached the end and there is not a new line at the end). For a printf, this is not that bad, but if I had something more complicated, it would result in a lot of repeated code. My workaround is putting what I want inside a function and just call the function after the loop, but I feel like there has to be a better way. Is there a better way to parse through a file like this? Preferably not character by character in case I have some formatted data that I need to use fscanf with.

KleberPF
  • 120
  • 1
  • 7
  • @EugeneSh. I'm sorry but I don't see how that solves the problem. I tried and got the same result. – KleberPF Apr 13 '21 at 22:21
  • If it's available to you, POSIX [`getline()`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getline.html) gives you the length of each line. It looks like you stop accumulating the length when you get a line back of length 1 (containing only a newline), or when you get `-1` returned (since the function formally returns `-1` and not `EOF`, even though `EOF` is usually `-1` — `EOF` can be any convenient negative number). – Jonathan Leffler Apr 13 '21 at 22:26
  • 1
    There's some confusion. It looks like you want to generate output when 2 consecutive newlines are seen, not when a newline is seen. So I wonder about your sample output and whether or not your input has a newline at the end of the file or not. The sample input you give appears to have a newline at the end of the file; just not 2. – William Pursell Apr 13 '21 at 22:27
  • @JonathanLeffler But my problem is the check after the end of the file. I'm already doing a check to see if the line contains just ```"\n"```. – KleberPF Apr 13 '21 at 22:28
  • I don't see what the problem is — `getline()` tells you how many characters it read, or `-1` if it did not read any. – Jonathan Leffler Apr 13 '21 at 22:30
  • 1
    @WilliamPursell the file does not have a new line at the end. My example file is: ```abcdf\nasd\n\nsdfsd\naa```. – KleberPF Apr 13 '21 at 22:30

2 Answers2

2

You can move your fgets call into the body of the while loop, while checking its result in the loop condition and in the printing condition. It should be properly initialized before the loop to a non-NULL value.

FILE* f;
// ...
int charCount = 0;
char line[20];
char *result = line;
while (result)
{
    result = fgets(line, sizeof line, f);
    if ( result == NULL || strcmp(line, "\n") == 0 )
    {
        printf("%d\n", charCount);
        charCount = 0;
    }
    else
    {
        charCount += strlen(line);
    }
}
Eugene Sh.
  • 17,802
  • 8
  • 40
  • 61
  • This is exactly what I wanted. I tried to come up with something like this but couldn't do it. I tried to do something like this, but the problem remained ([this](https://pastebin.com/yn0cwteY) is how I was doing it). I was almost there I guess. Anyway, thanks for the help. One more thing: could you explain what ```while(result)``` means? If the pointer is not NULL, the loops runs? – KleberPF Apr 13 '21 at 22:49
  • Yes. Pretty much the same as in your code - it loops while `fgets` returns non-NULL – Eugene Sh. Apr 13 '21 at 22:51
0

You could just do it the caveman way...

char ch;
int i = 0;
FILE *fp = fopen("yourfile.txt", "r");

while (feof(fp) == 0)
{
    i++;
    if ((ch = fgetc(fp)) == '\n')
        printf("%d\n", --i), i = 0;                 
}

if (i > 1) printf("%d\n", --i);
fclose(fp);
  • 1
    Suggest reviewing [Why is “while ( !feof (file) )” always wrong?](https://stackoverflow.com/q/5431941/2410359) – chux - Reinstate Monica Apr 14 '21 at 01:54
  • @chux I read a lot of "what can happen" in that post, but haven't seen it happen in 35 years of checking EOF. I'll just keep bangin' out caveman code that works 99.973% of the time, refuse to conform and leave the spaceship code to the "developers". Thanks for the concern though. –  Apr 14 '21 at 03:24