0

I'm trying to write a specific program that reads data from a file but I realized that when I read the file with fgetc, if I use fgets later, it doesn't have any output.

For example, this code:

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

int main() {
    FILE * arq = fopen("arquivo.txt", "r");
    char enter = fgetc(arq);
    int line_count = 1;
    
    while(enter != EOF) {
        if (enter == '\n') line_count++;
        enter = fgetc(arq);
    }

    printf("%d", line_count);
    char str[128];

    while(fgets(str, 128, arq)) printf("%s", str);
}

the second while doesn't print anything but if I delete the first while, the code prints the file content. Why is that happening?

5
  • 2
    If you loop until you reach EOF, what do you expect to be able to read afterwards? Commented Nov 18, 2021 at 2:00
  • 2
    Aside: fgetc(arq) returns 1 of 257 different values. Saving in a char will lose something. Use int enter. Commented Nov 18, 2021 at 2:00
  • Thank you very much for the clarifications. So, how do I reset it? Commented Nov 18, 2021 at 2:10
  • Use fseek() to go back to the beginning. Commented Nov 18, 2021 at 2:12
  • Why do you need the first loop? If you want to get the line count, just count how many times you call fgets(). Commented Nov 18, 2021 at 2:12

1 Answer 1

1

TLDR: rewind(arq); is what you want

When you read from a file, the internal file pointer advances as you read, so that each subsequent read will return the next data in the file. When you get to the end, all subsequent reads will return EOF as there is nothing more to read.

You can manipulate the internal file pointer with the fseek and ftell functions. fseek allows you to set the internal file pointer to any point in the file, relative to the beginning, the end, or the current position. ftell will tell you the current position. This allows you to easily remember any position in the file and go back to it later.

SYNOPSIS

 #include <stdio.h>

 int fseek(FILE *stream, long offset, int whence);

 long ftell(FILE *stream);

 void rewind(FILE *stream);

DESCRIPTION

The fseek() function sets the file position indicator for the stream pointed to by stream. The new position, measured in bytes, is obtained by adding offset bytes to the position specified by whence. If whence is set to SEEK_SET, SEEK_CUR, or SEEK_END, the offset is relative to the start of the file, the current position indicator, or end-of-file, respec‐ tively. A successful call to the fseek() function clears the end-of-file indicator for the stream and undoes any effects of the ungetc(3) function on the same stream.

The ftell() function obtains the current value of the file position indicator for the stream pointed to by stream.

The rewind() function sets the file position indicator for the stream pointed to by stream to the beginning of the file. It is equivalent to:

  (void) fseek(stream, 0L, SEEK_SET)

except that the error indicator for the stream is also cleared (see clearerr(3)).

One caveat here is that the offsets used by fseek and returned by ftell are byte offsets, not character offsets. So when accessing a non-binary file (anything not opened with a "b" modifier to fopen) the offsets might not correspond to characters exactly. It should always be ok to pass an offset returned by ftell back to fseek unmodifed to get to the same spot in the file, but trying to compute offsets otherwise may be tricky.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.