Моя функция пропускает параметр цикла в C ++ - PullRequest
1 голос
/ 13 марта 2019

Моя функция GetMark (), которая должна проверять правильный диапазон и впоследствии возвращать значение, если верный для данного массива застревает в бесконечном цикле, когда параметр задан вне допустимого диапазона, прежде чем я добавлю Функция SearchMark () работала правильно и зацикливалась только до тех пор, пока пользователь наконец не ввел значение в заданном диапазоне (0 - 100), но теперь, после того, как задано первое значение вне диапазона, оно зацикливается независимо от того, что введено, я буду благодарен за какие-либо предложения. полный код:

int GetMark(int ModuleIndex) //user input function
{
    bool help;
    if (ModuleIndex < 0 || ModuleIndex >100)
    {
        help = false;
        while (help != true)
        {
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
            cout << "hey, that's a invalid value, try again!" << endl;
            GetMark(ModuleIndex);
            if ((ModuleIndex > 0) &&( ModuleIndex < 101))
            {
                help = true;
            }
        }
    }

    return ModuleIndex;
}

int SearchMark(int A[], int a) //search grades array for numbers of specific grades
{
    int i = 0;
    int ii = 0;

    while (i < 12)
    {
        if (A[i] == a)
            ii++;
        i++;
    }
    cout << "Mark " << a << " was found: " << ii << " times" << endl;
    return 0;
}



int main()
{
    int marks[12]; 
    int i = 0;
    int sum = 0;
    int grades[12];

    while (i < 12)
    {
        cout << "enter mark (0 - 100): " << endl;
        cin >> marks[i];
        GetMark(marks[i]);
        sum = sum + marks[i];
        if (marks[i] > 69)
        {
            grades[i] = 1;
        }
        else if (marks[i] > 59 && marks[i] < 70)
        {
            grades[i] = 2;
        }
        else if (marks[i] > 49 && marks[i] < 60)
        {
            grades[i] = 22;
        }
        else if (marks[i] > 39 && marks[i < 50])
        {
            grades[i] = 3;
        }
        else if (marks[i] < 35)
        {
            grades[i] = 4;
        }
        i++;
    }
    sum = sum / 12;
    cout << "your average is: " << sum  << endl;




    if (sum > 69)
    {
        cout << "You passed with 1st!" << endl;
    }
    else if ((sum > 59) && (sum < 70))
    {
        cout << "You passed with 2i!" << endl;
    }
    else if ((sum > 49) && (sum < 60))
    {
        cout << "You passed with 2ii!" << endl;
    }
    else if ((sum > 39) && (sum < 50))
    {
        cout << "You passed with 3rd!" << endl;
    }
    else if (sum < 40)
    {
        cout << "Your average is too low! You failed." << endl;
    }


    i = 0;
    while (i < 12)
    {
        if (marks[i] < 35)
        {
            cout << "Referred in module " << i + 1 << " mark too low." << endl;
        }
        i++;
    }

    SearchMark(grades, 1);
    SearchMark(grades, 2);
    SearchMark(grades, 22);
    SearchMark(grades, 3);
    SearchMark(grades, 4);

    return 0;
}`

Ответы [ 5 ]

3 голосов
/ 13 марта 2019

Эта функция слишком сложна для того, что она делает.Просто зациклите значение, пока оно плохое, и запросите новое значение:

int GetMark(int ModuleIndex) {
    while (ModuleIndex < 0 || ModuleIndex > 100) {
        std::cout << "Invalid value.\n"
        std::cin >> ModuleIndex;
    }
    return ModuleIndex;
}

Рекурсия очень удобна в теоретическом анализе, но на практике это почти всегда ошибка.

1 голос
/ 13 марта 2019

Сочетание того, как вы определили GetMark, и способа его использования, является ошибочным.

Независимо от того, что вы делаете в GetMark, значение, введенное в main, не изменяется.

Измените GetMark на:

int GetMark()
{
   std::cout << "enter mark (0 - 100): " << std::endl;
   int mark;
   while ( std::cin >> mark )
   {
      if (  mark >= 0 && mark <= 100)
      {
         return mark;
      }

      std::cout << "Invalid value " << mark << std::endl;
      std::cout << "enter mark (0 - 100): " << std::endl;
   }

   // Unable to read.
   // Throw exception, or exit with an error message.
}

и измените его использование.Вместо

cout << "enter mark (0 - 100): " << endl;
cin >> marks[i];
GetMark(marks[i]);

используйте

marks[i] = GetMark();

Рабочая версия GetMark:

int GetMark()
{
   std::cout << "enter mark (0 - 100): " << std::endl;

   std::string line;
   while ( getline(std::cin, line) )
   {
      std::istringstream str(line);
      int mark;
      if ( str >> mark )
      {
         if (  mark >= 0 && mark <= 100)
         {
            return mark;
         }
      }
      std::cout << "Invalid input: " << line << std::endl;
      std::cout << "enter mark (0 - 100): " << std::endl;
   }

   // Unable to read.
   // Throw exception, or exit with an error message.
   return 0;
}

Live Demo .

1 голос
/ 13 марта 2019

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

int GetMark(int ModuleIndex) //user input function
{
    bool help;
    if (ModuleIndex < 0 || ModuleIndex >100)
    {
        help = false;
        while (help != true)
        {
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
            cout << "hey, that's a invalid value, try again!" << endl;
            cout << "enter mark (0 - 100): " << endl;
            cin >> ModuleIndex;
            if ((ModuleIndex > 0) &&( ModuleIndex < 101))
            {
                help = true;
            }
    }
}
    return ModuleIndex;
}
1 голос
/ 13 марта 2019

Это, очевидно, в вас getMark, внутри цикла while, который вы вызываете getMark рекурсивно с тем же недействительным значением ModuleIndex.Так что вам нужно получить его из стандартного ввода перед рекурсией.Например:

int GetMark(int ModuleIndex){
    bool help;
    if (ModuleIndex < 0 || ModuleIndex > 100){
        help = false;
        while (help != true){
                cout << "enter new ModuleIndex: \n";
                cin >> ModuleIndex;
                GetMark(ModuleIndex);
                // ...
        }

        return ModuleIndex;
    }

Ваш код не читается, кроме того, вы можете использовать класс std::vector.

Я предлагаю проверить этот код:

int GetMarkIndex(const std::vector<double>& vMarks, const double Search) {
    auto beg{ vMarks.begin() }, end{ vMarks.end() };
    while (beg != end && *beg != Search)
        ++beg;
    return beg != end ? beg - vMarks.begin() : -1;
}

int main() {

    std::vector<double> marks(5);
    int value;

    auto i{ 0U };
    auto sz{ marks.size() };
    while (i != sz) {
        std::cout << "Enter marks 1-->100" << std::endl;
        if (cin >> value && value > 0 && value < 101) {
            marks[i] = value;
            ++i;
        }
        else
            std::cout << "Invalid input!" << std::endl;
    }

    for (auto e : marks)
        cout << e << ", ";
    std::cout << std::endl;

    double Search = 15;
    auto index{GetMarkIndex(marks, Search)};

    (index != -1) ? (std::cout << Search << " Found at index: " << index) : (std::cout << Search << " Not found!" << std::endl);


    std::cout << std::endl;
}
1 голос
/ 13 марта 2019

Вам необходимо разрешить пользователю указывать новое значение меток [i] / ModuleIndex в GetMarks.После очистки cin прочитайте новое значение из cin.Вам также необходимо вернуть это значение, чтобы метки main [i] могли быть обновлены на это значение вместо исходного значения вне диапазона.

...