0

Im using fgets(learner.name,21,stdin) to Input the name of the student but when i run the program ,it shows " Enter your name " and skips to "Enter your marks in 5 subjects. "

can someone explain me why this happening?Because it is same with cin.getline() function.

gets_s() function is not working compiler shows " 'gets_s' was not declared in this scope"

#include<iostream>
#include<stdio.h>
#include<cstdlib>
using namespace std;
struct Student
{
    int rollno;
    char name[21];
    float marks[5];
    char grade;
};
Student learner ;
int main()
{
    cout<<"\n"<<"Enter Roll number: ";
    cin>>learner.rollno;
    cout<<"\n"<<"Enter your name: ";
    fgets(learner.name,21,stdin);
    cout<<"\n"<<"Enter your marks in 5 subjects: "<<"\n";
    for(int i = 0;i <5;++i)
    {
        cout<<"\n"<<"Subject"<<i+1<<":";
        cin>>learner.marks[i];
    }
    float avg ,total;
    total =  (learner.marks[0]+learner.marks[1]+learner.marks[2]+learner.marks[3]+learner.marks[4]);
    avg = total/5;
    if(avg<50)
        learner.grade = 'D';
    else if(avg<60)
        learner.grade = 'C';
    else if(avg<80) 
        learner.grade = 'B';
    else
        learner.grade = 'A';
    cout<<"\n"<<"\n"<<"Student result: \n";
    cout<<"Roll Number: "<<learner.rollno<<"\t";
    cout<<"Name: ";
    cout.write(learner.name,21);
    cout<<"\n"<<"Total Marks: "<<total;
    cout<<"\t"<<"Grade: "<<learner.grade<<endl;
    system("pause");
    return 0;
}

here is the output:

  Enter Roll number: 22
  Enter your name:
  Enter your marks in 5 subjects:

  Subject1:
Community
  • 1
  • 1
WildFire
  • 79
  • 1
  • 9
  • 1
    It is a bad idea to mix formatted I/O (`cin >> learner.rollno`) with line oriented input (`cin.getline()`) on the same stream because they handle newlines differently. The `cin >>rollno` will leave a newline in the stream, waiting to be read, and it will cause `fgets()` or `cin.getline()` to return immediately. It is also a rather poor idea to mix C I/O (`fgets()`) with C++ stream I/O on the same device (standard input in this case) – Peter Feb 25 '18 at 07:09
  • http://stackoverflow.com/questions/21567291/why-does-stdgetline-skip-input-after-a-formatted-extraction – chris Feb 25 '18 at 07:16
  • So then what do i do ? – WildFire Feb 25 '18 at 08:07

2 Answers2

0

The reason is that when you type roll no and press enter, cin only reads the number, not the newline (this is the default behaviour.). This newline remains in the input stream and when you execute fgets(), it takes in the newline character.
To change this you could use cin >> noskipws >> learner.rollno;

  • This will not fix the problem unless the user behaves in specific ways .... which are unusual for users. – Peter Feb 25 '18 at 07:11
  • It was one of many solutions. (not the best, i agree) – NikhilMTomy Feb 25 '18 at 07:13
  • Your change will affect only the reading of the roll number. A following `fgets` call will still have the same problem. – chris Feb 25 '18 at 07:17
  • I meant to use noskipws for all `cin` – NikhilMTomy Feb 25 '18 at 07:18
  • Regardless of where you apply `noskipws`, how is skipping less whitespace going to help when the problem is extra whitespace? `noskipws` is sticky, so it will affect all future formatted input operations on `cin` anyway. What I meant was that it doesn't affect `fgets` or `getline`. – chris Feb 25 '18 at 07:19
  • Its not working . – WildFire Feb 25 '18 at 08:13
0

stdin buffer is not cleared after cin>>learner.rollno;, use getchar() to clear/flush the stdin buffer and then use cin.getline() as

cin.getline(learner.name,'\n');
Achal
  • 11,821
  • 2
  • 15
  • 37
  • It is working now, can you explain me in depth,sir . – WildFire Feb 25 '18 at 08:15
  • And also when use getchar() after ' cin>>learner.rollno; ', The subject(s) are skipped not taking any input and print the final results . Why ? – WildFire Feb 25 '18 at 08:20
  • @WILDFIRE once `cin >>rollno` executed, there is a new line left in the `stdin` stream thats why second time when you try to put something into `same stream` its(`stdin` buffer) not clear(previous `\n` is there inside `stdin`). So clear the `stdin` buffer by using `__fpurge(stdin)` or use `getchar()` after every `cin` statement. – Achal Feb 25 '18 at 08:30
  • `__fpurge(stdin)` is not portable, you can see it in `man 3 fpurge`, So I suggest you to use `getchar()` – Achal Feb 25 '18 at 08:31
  • okay thank you ,sir. – WildFire Feb 25 '18 at 15:05