Ok I'm trying to do this program where I have to let the user enter students names followed by their test score. I'm trying to set it up so I'll have an array of names and an array of grades. I'm having trouble adding the names to the array. I tried to call cin.getline() inside the for loop and assign that to each subscript in the array. However, it fails miserably. Can somebody point me in the right direction?
#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[startSc开发者_如何学JAVAan] = 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);
}
You are not taking into account newline characters.
This line:
cin >> numTestScores;
Reads a number from the input, but NOT the newline character. So if you typed 8<enter> you read the 8 but the newline is not read from the input.
So the first time you go into the loop and do this:
cin.getline(name,30);
This reads the new line character that you typed after the 8 (and nothing else).
Couple of other gotchas...
1) Forgot to read and throw away newline.
cin >> numTestScores;
Solutions:
// 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: Don't use new/delete in C++ code
You can new dynamic objects but remembering to delete them is hard. You should be using smart pointers or containers to control the lifespan of dynamic objects.
studentNames = new string[numTestScores];
testScorePtr = new double[numTestScores];
In this situation it is better to use std::vector.
std::vector<std::string> studentNames(numTestScores);
std::vector<double> testScorePtr(numTestScores);
3: Don't use fixed size size array for user input:
cin.getline(name,30);
You are just asking for the user to crash your program. By typing in a realy long name.
Use the version that reads a line into a std::string. The string will expand as required.
std::getline(std::cin, studentNames[i]);
4: You don't need endl here. Use endl when you want the buffer to flush. I use it all the time so its actually fine. Just wanted to make sure you knew it flushed the buffer.
cout << studentNames[i] <<endl;
4: Not sure what this is for. Reading and throwing away the first character of the next line!!!!!!
cin.get();
5: Note this works fine. As the >> operator ignores the newline character as it searches for the next score.
//Get a test score.
//cout << "Enter test score "
//<< (i + 1) << ": ";
//cin >> testScorePtr[i];
6: Just like I predicted above you forgot to delete one of the arrays. Just use a vector. Any place where you use new/delete you are writing code like it was C. Good C++ code should have practically no deletes in it (unless you are writing the smart pointer/container).
delete [] testScorePtr;
7: You know there is a std::sort method.
void sort(double* score, int size)
8: You can get close with std::accumulate
double average(double* score, int numScores)
精彩评论