简体   繁体   中英

Using fscanf until EOF without using getc

I have a text file of composed of sequences of 2 bytes which I have to store in an array.

I have declared FILE *ptr .

How can I loop until EOF without using the method:

while(c = getc() != EOF)
{
// do something 
}

I want to implement something along the lines of (PSEUDOCODE):

while (ptr is not pointing to the end of the file)
{
fscanf(...)  // I will read in the bytes etc.
}

The getc() method wouldn't work well for me because I am reading in blocks of 2 bytes at a time.

You can use fread to read more than one byte at a time. fread returns the number of items it was able to read.

For example, to read 2-byte chunks you might use:

while ((fread(target, 2, 1, ptr) == 1) {
    /* ... */
}

Here 2 is the number of bytes in each "item", and 1 is the number of "items" you want to read on each call.

In general, you shouldn't use feof() to control when to terminate an input loop. Use the value returned by whichever input routine you're using. Different input functions vary in the information they provide; you'll have to read the documentation for the one you're using.

Note that this will treat an end-of-line as a single '\\n' character. You say you're reading from a text file; it's not clear how you want to handle line endings. You should also decide what you want to do if the file has an odd number of characters.

Another option is to call getc() twice in the loop, checking its result both times.

The only way to tell when you've reached the end of the file is when you try to read past it, and the read fails. (Yes, there is an feof() function, but it only returns true after you've tried to read past the end of the file.)

This means that, if you're going to use fscanf() to read your input, it's the return value of fscanf() itself that you need to check.

Specifically, fscanf() returns the number of items it has successfully read, or EOF (which is a negative value, typically -1) if the input ended before anything at all could be read. Thus, your input loop might look something like this:

while (1) {
    /* ... */

    int n = fscanf(ptr, "...", ...);

    if (n == EOF && !ferror(ptr)) {
        /* we've reached the end of the input; stop the loop */
        break;
    } else if (n < items_requested) {
        if (ferror(ptr)) perror("Error reading input file");
        else fprintf(stderr, "Parse error or unexpected end of input!\n");
        exit(1);  /* or do whatever you want to handle the error */
    }

    /* ... */
}

That said, there may be other options, too. For example, if your input is structured as lines (which a lot of text input is), you may be better off reading the input line by line with fgets() , and then parsing the lines eg with sscanf() .

Also, technically, there is a way to peek one byte ahead in the input, using ungetc() . That is, you could do something like this:

int c;
while ((c = getc(ptr)) != EOF) {
    ungetc(c, ptr);
    /* ... now read and parse the input ... */
}

The problem is that this only checks that you can read one more byte before EOF; it doesn't, and can't , actually check that your fscanf() call will have enough data to match all the requested items. Thus, you still need to check the return value of fscanf() anyway — and if you're going to do that, you might as well use it for EOF detection too.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM