-4

In the Bellow C program, gets is not working so I have used scanf to get the student name from the standard input.

#include<stdio.h>
#include<string.h>

struct student
{
    char name[10];
    int roll, sub[6], total, age;
};

int take(int n, struct student s[])
{
    int i, j;

    for(i=0;i<n;i++)
    {
        s[i].total=0;
        printf("\n\nEnter the name of the %d student :",i+1);
        gets(s[i].name);//over here gets is not working
        //scanf("%s",s[i].name);
        printf("Roll no :");
        scanf("%d",&s[i].roll);
        printf("Enter your Age : ");
        scanf("%d",&s[i].age);
        for(j=0;j<6;j++)
        {
            printf("Enter the Marks of Subject %d : ",j+1);
            scanf("%d",&s[i].sub[j]);
            s[i].total=s[i].total+s[i].sub[j];
        }
    }
}

main()
{
    int n;
    struct student s[10];
    printf("Enter how Student Details you want to Enter : ");
    scanf("%d",&n);
    take(n, s);
}

How can I use gets?

Alex Lop.
  • 6,810
  • 1
  • 26
  • 45
Ford Ramsaki
  • 131
  • 1
  • 8

2 Answers2

1

Mixing scanf with gets or fgets can be problematic regarding newline handling.

Prior to your call to gets, you call scanf with a format string of "%d". This goes over any leading whitespace, then (loosely speaking) reads in a sequence of digits and stops at the first non-digit. When this call is done, there is a newline left in the input buffer (as well as any non-digits you may have entered after your digits).

When you then call gets, it reads up to and including the next newline, which the newline being discarded. This results in an empty string being read into s[i].name.

Before calling gets, you need to flush everything in the input buffer up to and including the next newline. You can do that with a getchar loop as follows:

int c;
while ((c=getchar()) != '\n' && c != EOF);

Also, you shouldn't use gets as it has no means to prevent overrunning your input buffer which could lead to undefined behavior. You should use fgets instead:

fgets(&s[i].name, sizeof(s[i].name);
if (strrchr(s[i].name, '\n') != NULL) {
    *strrchr(s[i].name, '\n') = 0;
}

The fgets function will include the newline in the read string if there is room, so the following statements will remove the newline if it exists.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • the `getchar()` loop is perfectly fine but can't the same be done with some fancy `scanf` pattern? – Ajay Brahmakshatriya Apr 17 '17 at 16:03
  • @AjayBrahmakshatriya I don't think there's a pattern that can do this. `scanf` patterns can be tricky to work with anyway, so better to use something more straightforward. – dbush Apr 17 '17 at 16:27
  • I was thinking something like `scanf("%*s");`, but yes, a for loop with check on `'\n'` and `EOF` is much easier to understand. – Ajay Brahmakshatriya Apr 17 '17 at 16:30
0

I have figured out some mistakes that might be causing the problem.

First define a return type of main function (generally int main()).

Declare the array of structure variable globally, because it might be restricted to access the elements of structure with gets since gets faces security problems (don't know much about it).

You must not use gets, instead you can do this by using scanf only. It stops taking input when first white space occurs when used in layman format.

Use scanf in this way to make it accept whitespaces :

scanf("%[^\n]s",s[i].name);
Mahesh Suthar
  • 146
  • 1
  • 12