Home > Back-end >  Can someone please explain why I'm getting infinite loop in this code?
Can someone please explain why I'm getting infinite loop in this code?

Time:09-19

#include<stdio.h>


int main()
{
    char name[20];
    FILE *fptr=fopen("Student1.txt","w");
    fputc('J',fptr);
    fclose(fptr);
   
    
    FILE *ptr=fopen("Student1.txt","r");
    char ch;
   // ch=fgetc(ptr);
    fscanf(ptr,"%c",&ch);
    while(ch!=EOF)
    {
        printf("%c",ch);
        fscanf(ptr,"%c",&ch);
    }
    printf("\n");
    fclose(ptr);

    return 0;
}

I have been getting an infinite loop when I run this code.

I'm stuck at this code for so long now.

Please try to help.

CodePudding user response:

An infinite loop means that the loop condition ch != EOF remains true forever. The only way you set ch is via the two calls to fscanf(ptr,"%c",&ch);. fscanf() returns EOF when the end of a file is reached which is different than setting the (out) argument ch. Here is how I would write it:

#include <stdio.h>

int main() {
    FILE *fptr=fopen("Student1.txt","w");
    if(!fptr) {
        printf("fopen failed\n");
        return 1;
    }
    fputc('J',fptr);
    fclose(fptr);

    FILE *ptr=fopen("Student1.txt","r");
    if(!ptr) {
        printf("fopen failed\n");
        return 1;
    }
    for(;;) {
        char ch;
        int r = fscanf(ptr,"%c",&ch);
        if(r == EOF)
            break;
        if(r != 1) {
            printf("fscanf failed\n");
            return 1;
        }
        printf("%c",ch);
    }
    printf("\n");
    fclose(ptr);

    return 0;
}

Consider refactoring the two fopen() calls into a single FILE * fptr = fopen(..., "rw") then truncate the file with ftruncate(fileno(fptr), 0).

CodePudding user response:

The problem is that fgetch() and fscanf() have different interfaces.

  • fgetch() returns an int value to designate all the possible character values (from 0 to 255) and also EOF (which is none of them, generally implemented as -1). fgetch() returns EOF to indicate the end of file condition (which is not a character, but merely a situation)
  • fscanf() stores a representation of the char just read in the variable pointed to. But it will never store EOF in the variable (indeed, it will store nothing at all, in the case of an end of file condition), as EOF doesn't represent a character, it is not worth storing it in a char variable.

fscanf() returns the number of format specifiers that it could satisfy, so in this case

    // ch=fgetc(ptr);
    fscanf(ptr,"%c",&ch);
    while(ch!=EOF)
    {
        printf("%c",ch);
        fscanf(ptr,"%c",&ch);
    }

that will never happen (It will, in case you enter a char value that could be converted as a signed integer into the value EOF has, just try to enter the character value 0xff (in case you can do that from the keyboard). But that is completely incorrect, as the character stored in the variable would be a true character (that happens to convert to -1 when converted to an int) and it can happen in the middle of a file. The infinite loop happens because on an end of file, nothing is stored on the char variable, and so ch never changes again, if it was not the magic character described above, it will never satisfy the condition to get out of the loop.

The actual behaviour of fscanf() is that it will return 1 for all the characters actually read, and 0, on satisfying the end of file condition. A good working example would be:

    while (fscanf(ptr, "%c", &ch) == 1) {
        printf("%c",ch);
        fscanf(ptr,"%c",&ch);
    }
  •  Tags:  
  • c
  • Related