cin.getline портит цикл - PullRequest
       1

cin.getline портит цикл

0 голосов
/ 29 апреля 2011

Хорошо, я пытаюсь сделать эту программу, где я должен позволить пользователю вводить имена учеников, а затем их результаты теста.Я пытаюсь настроить его, чтобы у меня был массив имен и массив оценок.У меня проблемы с добавлением имен в массив.Я попытался вызвать cin.getline () внутри цикла for и назначить его каждому индексу в массиве.Однако, это терпит неудачу с треском.Может ли кто-нибудь указать мне правильное направление?

#include<iostream>
#include<iomanip>
#include<string>
using namespace std;

//Function prototypes
void sort(double*, int);
double average(double*, int);
void drop(double*, int);

int main()
{   
    char ch;
    char name[30];
    int numTestScores;
    string *studentNames;
    double *testScorePtr;
    double testAverage;

    //Get the number of test scores.
    cout << "\nHow many test scores will you enter? ";
    cin >> numTestScores;

    //Validate the input.
    /*while (numTestScores < 0)
    {
        cout << "The number cannot be negative.\n";
        cout << "Enter another number: ";
        cin >> numTestScores;
    }*/

    // Allocate an array to hold the test scores
    studentNames = new string[numTestScores];
    testScorePtr = new double[numTestScores];

    //Fill the array with test scores.
    for(int i = 0; i < numTestScores; i++)
    {


        cout << "Enter name and test score for test # "
        << (i+1) << " : "<< endl;
        cin.getline(name,30);
        studentNames[i] = name;
        cout << studentNames[i] <<endl; //I tried to use this to see if the names were going into the array






        cin.get();
    }

        //Get a test score.
        //cout << "Enter test score "
            //<< (i + 1) << ": ";
        //cin >> testScorePtr[i];

        //Validate the input.
        /*while (numTestScores < 0)
        {
            cout << "Negative scores are not allowed.\n";
            cout << "Enter another score for this test: ";
            cin >> testScorePtr[i];*/






    // Sort the test scores.
    sort(testScorePtr, numTestScores);



    //Display the resulting data.
    cout << "\nThe test scores in ascending "
        << "order, and their average, are:\n\n";
    cout << "Score" <<endl;
    cout << "----" <<endl;

    for (int j = 0; j < numTestScores; j++)
    {
        cout << "\n" << fixed << setprecision(2)
             << setw(6) << testScorePtr[j];
    }

    //Drop The Lowest Grade
    drop(testScorePtr, numTestScores);


// Get the average of the test scores.
    testAverage = average(testScorePtr, numTestScores);


    cout << "\n\nAverage score: " << setprecision(2) << fixed << testAverage <<endl <<endl;

//  Free the dynamically-allocated memory.
    delete [] testScorePtr;
    testScorePtr = 0;

    return 0;
}


    //****************************************
    //Function sort
    //This function performs a selection sort
    //on the array pointed to by the score
    //parameter into ascending order. The size
    //parameter holds the number of elements.
    //*****************************************

    void sort(double* score, int size)
    { 
      int startScan, minIndex;
      double minValue;

      for (startScan = 0; startScan < (size - 1); startScan++)
      {
          minIndex = startScan;
          minValue = score[startScan];
          for(int index = startScan + 1; index < size; index++)
          {
              if (score[index] < minValue)
              {
                  minValue = score[index];
                  minIndex = index;
              }
          }
          score[minIndex] = score[startScan];
          score[startScan] = minValue;
      }
    }

    void drop(double* score, int size)
    {

        score[0] = 0;
    }

    //*************************************************
    //Function average
    //This function calculates and returns the 
    //average of the values stored in the array
    //passed into the scores parameter. The
    //parameter numScors holds the number of elements in the array

    double average(double* score, int numScores)
    {
        double total = 0; //Accumulator
        numScores--;
        //Calculate the total of the scores.
        for (int k = 0; k <= numScores ; k++)
        {
            total += score[k];
        }
        //Return the average score.
        return (total/numScores);
    }

1 Ответ

2 голосов
/ 29 апреля 2011

Вы не учитываете символы новой строки.

Эта строка:

cin >> numTestScores;

Считывает число из ввода, но НЕ символ новой строки.Поэтому, если вы набрали 8 , вы читаете 8, но новая строка не читается с ввода.
Итак, когда вы в первый раз заходите в цикл и делаете это:

cin.getline(name,30);

Это читаетсимвол новой строки, который вы ввели после 8 (и ничего больше).

Пара других ошибок ...

1) Забыл прочитать и выбросить новую строку.

cin >> numTestScores;

Решения:

// 1: Read the line into a string then read the value from the string.
std::string testScoresString;
std::getline(std::cin, testScoresString);

std::stringstream testScoreStream(testScoreString);
testScoreStream >> numTestScores

// 2: Use boost::lexical cast on the string stream:
std::string testScoresString;
std::getline(std::cin, testScoresString);

testScoreStream = boost::lexical_cast<int>(testScoreString);

// 3: Read number then ignore input to the new line character
cin >> numTestScores;
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n')

2: Не используйте new / delete в коде C ++
Вы можете создавать новые динамические объекты, но забыть удалить их сложно.Вы должны использовать умные указатели или контейнеры для управления сроком службы динамических объектов.

studentNames = new string[numTestScores];
testScorePtr = new double[numTestScores];

В этой ситуации лучше использовать std :: vector.

std::vector<std::string> studentNames(numTestScores);
std::vector<double>      testScorePtr(numTestScores);

3: Donне используйте массив фиксированного размера для ввода пользователем:

    cin.getline(name,30);

Вы просто просите пользователя завершить работу вашей программы.Вводя действительно длинное имя.
Используйте версию, которая читает строку в std :: string.Строка будет расширяться по мере необходимости.

std::getline(std::cin, studentNames[i]);

4: вам здесь не нужен endl.Используйте endl, когда вы хотите, чтобы буфер очищался.Я использую это все время, так что на самом деле все в порядке.Просто хотел убедиться, что вы знали, что буфер очищен.

    cout << studentNames[i] <<endl;

4: Не уверен, для чего это нужно.Чтение и отбрасывание первого символа следующей строки !!!!!!

    cin.get();

5: Обратите внимание, это работает нормально.Поскольку оператор >> игнорирует символ новой строки при поиске следующей оценки.

    //Get a test score.
    //cout << "Enter test score "
        //<< (i + 1) << ": ";
    //cin >> testScorePtr[i];

6: Как я и предсказывал выше, вы забыли удалить один из массивов.Просто используйте вектор.В любом месте, где вы используете new / delete, вы пишете код, подобный написанному на C. Хороший код C ++ не должен иметь практически никаких удалений (если вы не пишете умный указатель / контейнер).Вы знаете, что есть std :: sort метод .

void sort(double* score, int size)

8: Вы можете приблизиться с помощью std :: аккумулировать

double average(double* score, int numScores)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...