Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
TrickSonix
1 / 1 / 0
Регистрация: 04.07.2013
Сообщений: 12
#1

Пропускает операторы считывания информации после первой итерации - C++

22.08.2013, 21:31. Просмотров 718. Ответов 3
Метки нет (Все метки)

Доброго времени суток всем. Все кому лень читать предистории можете смело пропускать следующие строки, смотреть на код, и возникшую проблему которую я опишу под ним.
Я лишь недавно занялся изучением С++ по книге Дейтелов. На протяжении первых 5-6 глав там мусолят класс под названием GradeBook. Ну и я следуя инструкциям, и некоторым своим соображениям мусолил этот же класс вместе с книгой. В 5-ой главе, когда демонстрируют оператор выбора switch представляют текст программы на С++ этого класса вместе с добавлением сего оператора. Суть - считывание буквенных оценок, и, по окончанию ввода, вывод количества различных буквенных оценок. Кому интересно, в книге это страница 282(издание 2008 года). Мой же собственный код отличается от этого тем, что я попытался сделать так чтобы эта программа работала столько раз, сколько я захочу (цикл while с меткой). Вот как это получилось в итоге:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <cstdlib>
#include <iostream>
#include <string>
#include "GradeBook.h"
 
using namespace std;
 
int main()
{
    string nameOfCourse;
    string name;
    int choise = 0;
    char k = 'n';
    cout << "Enter name: " << endl;
    getline(cin, name);
    GradeBook gradeBook1(name); //создание класса с именем gradeBook1
 
    cout << "gradeBook1 created for: " << gradeBook1.getCourseName() << endl;
    do
    {
        cout << "\nPlease enter the course name for gradeBook:" << endl;
        getline( cin, nameOfCourse );
        gradeBook1.setCourseName(nameOfCourse); //эта функция изменяет первоначальное имя курса
        cout << endl;
    
        gradeBook1.displayMessage();
        cout << "\nWhat kind of operation would have you do?" << "\n1)Determine Class Average\n2)Input letter grades" << endl;
        cin >> choise;
        if (choise == 1)
        {
            gradeBook1.determineClassAverage();
        }
        else
        {
            if (choise == 2)
            {
                gradeBook1.inputGrades(); // а вот и функция которая считывает буквенные оценки и записывает их количесвто в свои внутренние переменные
                gradeBook1.displayGradeReport(); // Это функция отображения полученного результата после окончания ввода
            }
            else
                cout << "Incorrect number of operation." << endl;
        }
        cout << "Continue? (y/n)" << endl;
        cin >> k;
    }
    while (k != 'n'); //по умолчанию пользователь не хочет продолжать работать с программой и нужно ввести y чтобы продолжить
    system("PAUSE");
   return 0;
}
А вот собственно и проблема - после того как цикл срабатывает первый раз перестают работать некоторые операторы ввода информации. Если, например, ввести неправильно номер операции то он просто выдает текст который выводят все функции cout до момента когда нужно выбрать операцию. А если же выбрать операцию 2 то после того как заканчиваешь вводить оценки(признаком конца ввода является символ EOF) цикл начинает повторяться до бесконечности.
Ниже написаны функции класса, на всякий случай.
Для создания программ пользуюсь Dev-cpp 4.9.9.2
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include "GradeBook.h"
 
using namespace std;
 
GradeBook::GradeBook(string name)
{
    setCourseName(name);
    aCounter = 0;
    bCounter = 0;
    cCounter = 0;
    dCounter = 0;
    fCounter = 0;
}
 
void GradeBook::setCourseName(string name)
{
    if (name.length() <= 25)
        courseName = name;
    else
    {
        courseName = name.substr(0,25);
        cout << "Name \"" << name <<"\" exceed maximum length.\nLimiting courseName to first 25 characters.\n" << endl;
    }
}
 
string GradeBook::getCourseName()
{
    return courseName;
}
 
void GradeBook::displayMessage()
{
    cout << "Welcome to Grade Book for\n" << getCourseName() << "!" << endl;
}
 
void GradeBook::determineClassAverage()
{
    int gradeCounter = 0;
    int grade = 0;
    double average = 0;
    int total = 0;
    cout << "Enter grade or -1 to end: " << endl;
    cin >> grade;
    while (grade != -1)
    {
        gradeCounter += 1;
        total = total + grade;
        cout << "Enter grade or -1 to end: " << endl;
        cin >> grade;       
    }
    if (gradeCounter != 0)
    {
        average = static_cast<double>(total)/gradeCounter;
        cout << "\nTotal of all " << gradeCounter << " grades entered is " << total << endl;
        cout << "Class average is " << setprecision(2) << fixed << average << endl;
    }
    else
        cout << "No grades were entered." << endl;
}
 
void GradeBook::inputGrades()
{
    int grade = 0;
    cout << "Enter the letter grades." << endl << "Enter the EOF character to end input." << endl;
 
    while ((grade = cin.get()) != EOF)
    {
        switch (grade)
        {
            case 'A':
            case 'a':
                aCounter++;
                break;
            case 'B':
            case 'b':
                bCounter++;
                break;
            case 'C':
            case 'c':
                cCounter++;
                break;
            case 'D':
            case 'd':
                dCounter++;
                break;
            case 'F':
            case 'f':
                fCounter++;
                break;
            case '\n':
            case '\t':
            case ' ':
                break;
            default:
                cout << "Incorrect letter grade entered. Enter another." << endl;
                break;
        }
    }
}
 
void GradeBook::displayGradeReport()
{
    cout << "\nNumber of students who received each letter grade:"
        << "\nA: " << aCounter
        << "\nB: " << bCounter
        << "\nC: " << cCounter
        << "\nD: " << dCounter
        << "\nF: " << fCounter
        << endl;
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
22.08.2013, 21:31     Пропускает операторы считывания информации после первой итерации
Посмотрите здесь:

C++ Как очистить консоль после итерации цикла?
C++ Программа пропускает ввод первой строки
C++ Встретил незнакомые операторы, нужно больше информации
C++ Строки: уничтожить в строке запятые перед первой точкой, заменить знаком + все цифры 3я после первой точки
C++ Не даёт вводить (пропускает, проходит мимо), после первого ввода
C++ Не получается после первой итерации считать во вложенном (ss>>ch)
Пропуск вызова cin.getline в первой итерации цикла C++
C++ Есть ли в С++ функция для считывания информации с файла с подробной настройкой?
C++ Почему не меняется imin после первой итерации?
C++ Как убрать с конца строки знак переноса, после считывания ее из файла?
C++ Пропускает ввод данных после for
C++ Почему после считывания матрицы из файла начинается повторное считывание?

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
alsav22
5413 / 4809 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
22.08.2013, 21:38     Пропускает операторы считывания информации после первой итерации #2
Если после cin >> идёт getline() или cin.get(), то нужно так писать:
C++
1
2
3
4
...
(cin >> choise).get();
...
(cin >> k).get();
...
А лучше, на всякий случай, всегда так писать.
TrickSonix
1 / 1 / 0
Регистрация: 04.07.2013
Сообщений: 12
22.08.2013, 21:46  [ТС]     Пропускает операторы считывания информации после первой итерации #3
Спасибо, помогло. А не могли бы вы объяснить, если вам не сложно, в чем разница между простым оператором cin и оператором написанным подобным образом? Ну то есть в чем суть явления описанного мной казуса?
alsav22
5413 / 4809 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
22.08.2013, 22:04     Пропускает операторы считывания информации после первой итерации #4
После работы cin >> в потоке чтения остаётся символ новой строки '\n' (попадает туда при нажатии Enter). Если функция getline() встречает такой символ первым, то для неё это пустая строка: чтение останавливается, символ '\n' извлекается из очереди (в отличие от get(char* s, streamsize n)), но не сохраняется, в строку ввода помещается '\0' . Флаг ошибки НЕ устанавливается (в отличие от get(char* s, streamsize n)), код идёт дальше.

Добавлено через 3 минуты
А в inputGrades(), функция cin.get() просто извлечёт '\n', оставшийся в потоке, и код, без остановки на ввод, пойдёт дальше.
Yandex
Объявления
22.08.2013, 22:04     Пропускает операторы считывания информации после первой итерации
Ответ Создать тему
Опции темы

Текущее время: 18:44. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru