Программа пропускает ввод данных или ломается

при вводе в students[i].fio(там где комментарий) программа ломается, либо вообще пропускает ввод. Пробовал и с char и string и cin и getline. Направьте молодой ум, помогите мученику.

#include <iostream>
#include <windows.h>
#include <string>
using namespace std;

int main()
{
  setlocale(LC_ALL, "ru_RU.UTF-8");
  SetConsoleCP(1251);
  SetConsoleOutputCP(1251);
  struct Student
  {
    string fio;
    int group;
    int yspeh[5];
    double sredn;
  };
  int n;
  cout << " Введите количество студентов: ";
  cin >> n;
  Student *students = new Student[n];
  for (int i = 0; i < n; i++)
  {
    cout << "Введите ФИО: ";
    cin >> students[i].fio; // тут ломается программа!!!!!!!!!!!!!!!!!!11
    cout << "Введите групу: ";
    cin >> students[i].group;
    cout << "Введите оценки: ";
    for (int j = 0; j < 5; j++)
    {
      cout << j + 1 << " : ";
      cin >> students[i].yspeh[j];
    }
  }
  double sredn = 0;
  for (int i = 0; i < n; i++)
  {
    for (int j = 0; j < 5; j++)
    {
      sredn += students[i].yspeh[j];
    }
    students[i].sredn = sredn / 5.0;
    sredn = 0;
  }
  int temp;
  for (int i = 0; i < n; i++)
  {
    for (int j = i; j < n; j++)
    {
      if (students[i].sredn > students[j].sredn)
        swap(students[i], students[j]);
    }
  }
  for (int i = 0; i < n; i++)

  {
    cout << "ФИО\t" << students[i].fio << "\n"; 
    cout << "Номер группы\t" << students[i].group << "\n";
    cout << "Оценки\t";
    for (int j = 0; j < 5; j++)
    {
      cout << students[i].yspeh[j] << "\t";
    }
    cout << "\n";
    cout << "Среднее знач:\t" << students[i].sredn << "\n";
  }
  string vopros;
  cout << "Вывести студентов с оценкой 4 или 5?" << endl;
  cin >> vopros;
  if (vopros != "нет")
  {
    int check;
    if (vopros == "4")
    {
      for (int i = 0; i < n; i++)
      {
        check = 0;
        for (int j = 0; j < 5; j++)
        {
          if (students[i].yspeh[j] != 4)
            check = 1;
          break;
        }

        if (check == 0)
        {
          cout << "ФИО\t" << students[i].fio << "\n";
          cout << "Номер группы\t" << students[i].group << "\n";
          cout << "Оценки\t";
          for (int j = 0; j < 5; j++)
          {
            cout << students[i].yspeh[j] << "\t";
          }
          cout << "\n";
          cout << "Среднее знач:\t" << students[i].sredn << "\n";
        }
      }
    }
    else if (vopros == "5")
    {
      for (int i = 0; i < n; i++)
      {
        check = 0;
        for (int j = 0; j < 5; j++)
        {
          if (students[i].yspeh[j] != 5)
            check = 1;
          break;
        }

        if (check == 0)
        {
          cout << "ФИО\t" << students[i].fio << "\n";
          cout << "Номер группы\t" << students[i].group << "\n";
          cout << "Оценки\t";
          for (int j = 0; j < 5; j++)
          {
            cout << students[i].yspeh[j] << "\t";
          }
          cout << "\n";
          cout << "Среднее знач:\t" << students[i].sredn << "\n";
        }
      }
    }
  }
  else
  {
    cout << "До свидания";
  }
  system("PAUSE");
}

Ответы (1 шт):

Автор решения: Stanislav Volodarskiy

Правило большого пальца: проверять что ввод был успешен. При не успешном вводе ломать программу быстро, чтоб только успеть напечатать диагностику.

Чтобы отладится после каждого ввода выводите на печать "я просил фамилию. вы ввели ...", "я просил номер группы, вы ввели ...". Вы многое узнаете про поток ввода и буферизацию.

Теперь по делу

Этот кусок кода вводит одно и только одно слово - фамилию:

string s;
cin >> s;

Следующий за ним кусок пытается ввести целое число:

int i;
cin >> i;

Но в потоке ввода остались инициалы или имя. Ошибка. А ошибки вы не проверяете. Поток переведён в ошибочное состояние. Вы больше ничего из него не прочитаете пока не сбросите ошибку.

Вам нужны

getline(cin, ...) чтобы читать строки целиком,

if (cin >> ...) для проверки ошибок,

cin.clear чтобы сбрасывать ошибки,

cin.ignore чтобы пропускать ошибочные данные из потока.

→ Ссылка