cin.getline пропускает напоминание о вводе, если пользователь вводит больший ввод, чем массив char - PullRequest
0 голосов
/ 29 сентября 2019

Я пытаюсь ввести данные в массив структуры, который содержит член массива char и член int, как здесь:

int main(){
    typedef struct {
        char name[10];
        int age;
    }Student;
    Student students[3];
    for (i=0;i<N;i++){
        cout<<"\n Enter name of student : "<< i+1<<" " ;
        cin.getline(students[i].name, 10);
        cout<<"\n Enter age of student : "<< i+1<<" ";
        cin>>students[i].age ;    
    }

Но если я введу имя с более чем 10 символами (чтопользователь может сделать), тогда остальные команды ввода игнорируются.

Я пытался добавить cin.ignore(), но это не помогло.

Я пытался использовать gets(students[i].name); с fflush(stdin);, но это тоже не помогло.

Я не могу использовать std::string.Какие-либо предложения?

1 Ответ

2 голосов
/ 29 сентября 2019

Я только что вспомнил док.из std::istream::getline():

Если функция не извлекает никаких символов (например, если число <1), выполняется settate (failbit). </p>

Это означает, что после ввода более 10 символов (включая EOL) std::cin находится в состоянии сбоя.Следовательно, никакие входные данные не могут быть извлечены, не реагируя на это.

Вы можете проверить это с помощью std::istream::fail().

Чтобы очистить состояние отказа, *Можно использовать 1019 *.

При подготовке MCVE я обнаружил еще одну слабость:

Смешивание std::istream::getline() с операторами входного потока >> требует особого внимания, поскольку

  • getline() читает до конца строки, но
  • operator>> читает пробелы (включая конец строки) перед фактическим значением.

Следовательно,ignore() следует использовать после ошибки в getline(), чтобы отбросить остаток строки, но ignore() следует использовать всегда после std::cin >> students[i].age, чтобы использовать конец строки, по крайней мере.

Итак, я пришелс этим:

#include <iostream>

int main()
{
  const unsigned N = 3;
  const unsigned Len = 10;
  struct Student {
    char name[Len];
    int age;
  };
  Student students[N];
  for (unsigned i = 0; i < N; ++i) {
    std::cout << "Enter name of student " << i + 1 << ": ";
    std::cin.getline(students[i].name, Len);
    if (std::cin.fail()) {
      std::cerr << "Wrong input!\n";
      std::cin.clear();
      std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
    std::cout <<"Enter age of student : " << i + 1 << " ";
    std::cin >> students[i].age;
    if (std::cin.fail()) {
      std::cerr << "Wrong input!\n";
      std::cin.clear();
    }
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
  }
  // check read
  std::cout << "\nStudents:\n";
  for (unsigned i = 0; i < N; ++i) {
    std::cout << i + 1 << ".: "
      << "name: '" << students[i].name << "'"
      << ", age: " << students[i].age << "\n";
  }
}

Ввод / вывод:

Enter name of student 1: Johann Sebastian
Wrong input!
Enter age of student 1: 23
Enter name of student 2: Fred
Enter age of student 2: 22
Enter name of student 2: Fritz
Enter age of student 2: 19

Students:
1.: name: 'Johann Se', age: 23
2.: name: 'Fred', age: 22
3.: name: 'Fritz', age: 19

Живая демонстрация на coliru

...