Question

I used fgets() and gets() also for getting a string as input inside a loop. In the first execution, it worked properly but in the second time, it skips the inputting step and straight away goes to the next line.

#include<stdio.h>
#include<conio.h>
struct student
{
    int roll,m[3];
    float avg;
    char name[30];
}s[5];
void main()
{
    int i;
    clrscr();
    printf("Enter thr student details:");
    for(i=0;i<5;i++)
    {
        printf("\nstudent[%d] name:",i+1);
        fgets(s[i].name,30,stdin);
        printf("student[%d] register number:  ",i+1);
        scanf("%d",&s[i].roll);
        printf("student[%d] marks:\n",i+1);
        scanf("%d%d%d",&s[i].m[0],&s[i].m[1],&s[i].m[2]);
        s[i].avg=(s[i].m[0]+s[i].m[1]+s[i].m[2])/3;
    }
    printf("-----------------------------------------------------------");
    printf("\n  NAME        REG.NO      AVERAGE");
    printf("\n-----------------------------------------------------------");
    printf("\n      DISTINCTION");
    for(i=0;i<5;i++)
        if(s[i].avg>74)
            printf("\n%-20s%-10d%.2f",s[i].name,s[i].roll,s[i].avg);
    printf("\n              FIRST CLASS");
    for(i=0;i<5;i++)
        if((s[i].avg<74)&&s[i].avg>50)
            printf("\n%-20s%-10d%.2f",s[i].name,s[i].roll,s[i].avg);
    printf("\n                 FAIL");
    for(i=0;i<5;i++)
        if(s[i].avg<50)
            printf("\n%-20s%-10d%.2f",s[i].name,s[i].roll,s[i].avg);
    getch();
}
Was it helpful?

Solution 3

as told by @chux , scanf leaves '\n' in the stdin ( memory buffer ) , and fgets() takes value until there is a '\n' in the buffer , in order to clear the buffer the statement fflush(stdin); is used before the fgets() statement

OTHER TIPS

Enter thr student details:
student[1] name:abcd <Enter>

fgets reads until the size limit is reached or EOF is returned or a new line (\n) character is encountered. In the above scenario, it reads abcd and also reads \n,and returns.

student[1] register number:  12<Enter>
student[1] marks:
12 13 14<Enter>

Now, you are using scanf to read the numbers. scanf with %d returns until a number is encountered or EOF is seen. It ignores all the new line characters.

After the above two steps you are left with an extra \n in the input stream.(since scanf doesn't actually read it).

Now when you have a next call for fgets, there is already a \n first. It returns there, without actually prompting for the next name.

Solution:

Put a getch(), after reading the marks. This removes the leading \n from the stream. Or, read the name using scanf itself.

scanf("%s", s[i].name);

scanf("%d%d%d") leaves the Enter or '\n' in stdin. The following fgets() then reads only "\n".

The best solution is to use the fgets()/sscanf() combination. Robust code checks the return results.

{
  char buf[100];
  printf("\nstudent[%d] name:",i+1);
  if (fgets(s[i].name, sizeof s[i].name, stdin) == NULL) 
    Handle_EOF();
  printf("student[%d] register number:  ", i+1);
  if (fgets(buf, sizeof buf, stdin) == NULL) 
    Handle_EOF();
  if (sscanf(buf, "%d", &s[i].roll) != 1) 
    Handle_InputError();
  printf("student[%d] marks:\n",i+1);
  if (fgets(buf, sizeof buf, stdin) == NULL) 
    Handle_EOF();
  if (sscanf(buf, "%d%d%d", &s[i].m[0], &s[i].m[1], &s[i].m[2]) != 3)
    Handle_InputError();
  s[i].avg = (s[i].m[0] + s[i].m[1] + s[i].m[2])/3;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top