Here is my first post. I am looking for a little guidance with my class project. I have all the logic pieces worked out, but I don't know how to import a scores.txt file into an array. For the sake of my testing I just statically entered some data into my array "item". The input file "scores.txt" must have the user enter the file name. The scores.txt file has a different number of entries. I didn't know if I needed to use a 2d array or if I can get by with a single array. I didn't want to go any further without asking first.

Thanks for any and all help I might find here.

I am going to keep working on this in the interim. Thanks again.

My scores.txt file looks like this:

8.2,9.3,8.5,9.5,9.6
7.2,9.3,9.0,9.9,8.5,9.5,9.6
6.2,9.3,9.9,8.5,9.5,9.6
5.2,9.3,9.0,9.9,8.5,9.5,9.6,9.9,9,9
8.2,9.3,9.0,9.9,8.5,9.5,9.6
7.2,9.3,9.0,9.9,8.5,9.5,
6.2,9.3,9.0,9.9,8.5,9.5,8.0,9.6
9.9,9.2,9.3,9.0,9.9,8.5,9.5,9.6,10.0,9.9

``````#include <iostream>

using namespace std;

int main()
{
double item[10] = {9.2,9.3,9.0,9.9,8.5,9.5,9.6,9.9};  //Declare an array item of ten components
double sum;
int divisor;
int counter;

sum = 0;
divisor = 0;
avg = 0;
counter = 0;
max = item[counter];
min = item[counter];

for (counter = 0; counter < 10; counter++)
{
item[counter];
sum = sum + item[counter];		// totals all the numbers
if (item[counter] <= 1)
divisor = counter;			// ignores 0 items so avg will calculate
else divisor = divisor++;
if (item[counter] > max)		// determines high score so it can be dropped
max = item[counter];
if(item[counter] < min && item[counter] != 0)			// determines low score so it can be dropped
min=item[counter];
avg = static_cast<double>(sum/divisor);		// calc avg with all non 0 scores
adjavg = static_cast<double>((sum-min-max)/(divisor-2));  // calc avg with high/lo dropped
}

cout << endl;

cout << "The sum of the numbers is: " << sum << endl;
cout << "Divisor =" << divisor << endl;
cout << "The average of the scores is: " << avg << endl;
cout << "The Max number is :" << max << endl;
cout << "The Min number is :" << min << endl;
//cout << "The numbers in reverse order are: ";
//Print the numbers in reverse order
//for (counter = 9; counter >= 0; counter--)
//{
//	cout << item[counter] << " ";
//	cout << endl;
//}

return 0;

}``````
2
Contributors
8
Replies
9
Views
9 Years
Discussion Span
Last Post by vmanes

We'll need a bit of clarification on the assignment. Is each row in the scores.txt file to be treated independantly? That is, for row 1, only five values are to be summed, averaged, etc? Then go on to row 2 (seven items), and so on?

Are you guaranteed that the last item of a row will not have a comma after it, and that no row will exceed 10 values?

It looks like you need to read a double, the get a char. If that char is a comma, read another double - storing these up to 10 doubles in the array, keeping count of how many are currently valid. At 10 items or when newline is encountered, begin your proccessing loop, using that counter as a limit rather than fixed value 10. Be sure to reset the variables that must start at 0.

Thanks for the reply. Each row is essential judges scores for an event. So all my avg/min/max are done on a row by row basis. I don't need any totals at the end.

Each row will have a minimum of 5 values and a max of 10. Each row in the array can have different number of entries, but again, no more than 10 and no less than 5. High and low scores are dropped.

I did alter my array to be item[10][10] since I know the max sizes. I also created a variable row for the row counter and counter will be the column counter.

``````#include <iostream>
#include <fstream.h>
#include <stdlib.h>

using namespace std;

int main()
{
double item[10][10];  //Declare an array item of ten by 10 components from scores.txt
double sum;
int divisor;
int row, counter;

sum = 0;
divisor = 0;
avg = 0;
row = 0;
counter = 0;
max = item[row][counter];
min = item[row][counter];

for (row = 0; row < 10; row++)
{
for (counter = 0; counter < 10; counter++)
{
item[row][counter];
sum = sum + item[row][counter];		// totals all the numbers
if (item[row][counter] <= 1)
divisor = counter;			// ignores 0 items so avg will calculate
else divisor = divisor++;
if (item[row][counter] > max)		// determines high score so it can be dropped
max = item[row][counter];
if(item[row][counter] < min && item[row][counter] != 0)			// determines low score so it can be dropped
min=item[row][counter];
avg = static_cast<double>(sum/divisor);		// calc avg with all non 0 scores
adjavg = static_cast<double>((sum-min-max)/(divisor-2));  // calc avg with high/lo dropped
}

cout << endl;

cout << "The sum of the numbers is: " << sum << endl;
cout << "Divisor =" << divisor << endl;
cout << "The average of the scores is: " << avg << endl;
cout << "The Max number is :" << max << endl;
cout << "The Min number is :" << min << endl;
}

return 0;

}``````

We'll need a bit of clarification on the assignment. Is each row in the scores.txt file to be treated independantly? That is, for row 1, only five values are to be summed, averaged, etc? Then go on to row 2 (seven items), and so on?

Are you guaranteed that the last item of a row will not have a comma after it, and that no row will exceed 10 values?

It looks like you need to read a double, the get a char. If that char is a comma, read another double - storing these up to 10 doubles in the array, keeping count of how many are currently valid. At 10 items or when newline is encountered, begin your proccessing loop, using that counter as a limit rather than fixed value 10. Be sure to reset the variables that must start at 0.

``````for (row = 0; row < 10; row++)
{
//reset sum before adding up next row of data!
for (counter = 0; counter < 10; counter++)
{
item[row][counter];//this does nothing - need to read into item[r][c]
//this is where it gets a little complex, determining if you're at end of line.
sum = sum + item[row][counter];		// totals all the numbers
.....``````

Please show us how you think you'll read from the file, and skip the rest of the loop when you've run out of data for that line.

I have a good level of flexability on how I read and calculate. I figured i would do one row at a time. Then move on the to the next. I can display the data as it's calculated. I hope that answers your question.

``````for (row = 0; row < 10; row++)
{
//reset sum before adding up next row of data!
for (counter = 0; counter < 10; counter++)
{
item[row][counter];//this does nothing - need to read into item[r][c]
//this is where it gets a little complex, determining if you're at end of line.
sum = sum + item[row][counter];		// totals all the numbers
.....``````

Please show us how you think you'll read from the file, and skip the rest of the loop when you've run out of data for that line.

Ok, so I am a lot closer now. I can import the file and it works fine, except it only reads the first row of data from scores.txt.

My second issue is that I can't make the error check work when importing the file. It just keeps crashing C++.

I am slowly getting the hang of this. Thanks for all the help.

``````// urban3.cpp
// program to import txt file into array.  then calculate the scores for each line,
// dropping the high and low scores first.

#include <iostream>
#include <cassert>
#include <fstream>
#include <string>
#include <iomanip>

using namespace std;

//Function Prototypes.
void getFiles(ifstream& file);
void importData(ifstream& file, double scores[], int& size);
void calcScores(double scores[], double& min, double& max, double& sum, double& total, int size);
void display(double scores[], double min, double max, double total, int size);

int main ()
{
// Declare maximum array size.
const int arraySize = 10;

// Declare variables.
ifstream file;
double scores[arraySize];
double maxScore = 0, minScore = 0, sumScore = 0, totalScore = 0;
int size;

// Call functions.
getFiles(file);
importData(file, scores,size);
calcScores(scores, maxScore, minScore, sumScore, totalScore, size);
display(scores, maxScore, minScore, totalScore, size);

return 0;
}

// Function to opens file named by user.
void getFiles(ifstream& file)
{
string filename;

cout <<"Enter the file name to open: ";
cin >> filename;
file.open(filename.c_str());
if (!file) {
cout << "Can't open file " << filename << " for reading" << endl;
}
else assert(file);
}

// Function to get scores from input file and puts them into an array.
void importData(ifstream& file, double scores[], int& size)
{
cout << fixed << showpoint << setprecision(2);
int i = 0;
while (file)
{
file >> scores[i];
i++;
}
size = i - 1;
}

// Function to calculate what scores to keep and their sum.
void calcScores(double scores[], double& min, double& max, double& sum, double& total, int size)
{
int i = 0, j = 0;

for(i = 0; i < size; i++)
{
// sum up all the scores
sum = sum + scores[i];
}
min = scores[0];
max = scores[0];

for(j = 0; j < size; j++)
{
if( min > scores[j])
{
min = scores[j];
}
if( max < scores[j])
{
max = scores[j];
}
}
total = sum - (max + min);
}

// Function to display all the scores, the min, the max and sum of those remaining.
void display(double scores[], double min, double max, double total, int size)
{
cout << fixed << showpoint << setprecision(1);
cout << endl << "Input file contains: : ";
for (int i = 0; i < size; i++)
cout << scores[i] << ", ";
cout << endl << "Dropped Scores: " << min << " and " << max << endl;
cout << fixed << showpoint << setprecision(2);
cout << "Points Received: " << total << endl << endl;
}``````

I don't see it reading a whole row from the data, only the first value of the first row. When your input statement then encounters the comma, input goes to a bad state and your while loop will end.

As I mentioned earlier, you need to get rid of the comma between data values. Try this:

``````void importData(ifstream& file, double scores[], int& size)
{
int i = 0;
char ch;
bool more_line = true;
while ( more_line &&  file >> scores[i] )
{
i++;
file.get( ch ); //read and remove the separator
if( ch == '\n' ) //if at end of line, time to quit
more_line = false;
}
size = i ;
}``````

Your cout to set precision and such has no purpose for input function.

This will read in one line's worth. It's up to you to figure out how to know when you've run out of lines. This function also has no way of knowing when it's reached the end of the array for storing input - what if a line should mistakenly contain more than 10 elements? Or, how can you make this a function you can use in any program, regardless of number of elements in a line?

One should strive for good general solutions, even when working on a very specific problem.

so I removed the cout for the input, i agree no point.

I removed the commas from scores.txt

So everything works fine if there is only a single line of scores in the txt file. If there are more than one line, it crashes the compiler.

``````// urban3.cpp
// program to import txt file into array.  then calculate the scores for each line,
// dropping the high and low scores first.

#include <iostream>
#include <cassert>
#include <fstream>
#include <string>
#include <iomanip>

using namespace std;

//Function Prototypes.
void getFiles(ifstream& file);
void importData(ifstream& file, double scores[], int& size);
void calcScores(double scores[], double& min, double& max, double& sum, double& total, int size);
void display(double scores[], double min, double max, double total, int size);

int main ()
{
// Declare maximum array size.
const int arraySize = 10;

// Declare variables.
ifstream file;
double scores[arraySize];
double maxScore = 0, minScore = 0, sumScore = 0, totalScore = 0;
int size;

// Call functions.
getFiles(file);
importData(file, scores,size);
calcScores(scores, maxScore, minScore, sumScore, totalScore, size);
display(scores, maxScore, minScore, totalScore, size);

return 0;
}

// Function to opens file named by user.
void getFiles(ifstream& file)
{
string filename;

cout <<"Enter the file name to open: ";
cin >> filename;
file.open(filename.c_str());
if (!file) {
cout << "Can't open file " << filename << " for reading" << endl;
}
else assert(file);
}

// Function to get scores from input file and puts them into an array.
void importData(ifstream& file, double scores[], int& size)
{
// cout << fixed << showpoint << setprecision(2);
int i = 0;
while (file)
{
file >> scores[i];
i++;
}
size = i - 1;
}

// Function to calculate what scores to keep and their sum.
void calcScores(double scores[], double& min, double& max, double& sum, double& total, int size)
{
int i = 0, j = 0;

for(i = 0; i < size; i++)
{
// sum up all the scores
sum = sum + scores[i];
}
min = scores[0];
max = scores[0];

for(j = 0; j < size; j++)
{
if( min > scores[j])
{
min = scores[j];
}
if( max < scores[j])
{
max = scores[j];
}
}
total = sum - (max + min);
}

// Function to display all the scores, the min, the max and sum of those remaining.
void display(double scores[], double min, double max, double total, int size)
{
cout << fixed << showpoint << setprecision(1);
cout << endl << "Input file contains: : ";
for (int i = 0; i < size; i++)
cout << scores[i] << ", ";
cout << endl << "Dropped Scores: " << min << " and " << max << endl;
cout << fixed << showpoint << setprecision(2);
cout << "Points Received: " << total << endl << endl;
}``````

OK, so you changed the rules of the game (been studying Captain Kirk?).

Now your read function just keeps on reading the data file, not getting stopped at the end of a line. What happens when you try to store the 11th data element in a 10 element array?

(BTW: It's not crashing the compiler, it's crashing at run time.)

You still need a way to know when you've reached the end of a line of data, when the lines will not all be same number of values.

This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.