I'm sure someone has seen this exact problem before but I never found a solution.. so I built my own version but I'm having some trouble. My output is going crazy and I don't even think it's reading my input correctly.. any help would be greatly appreciated. Basically I'm reading temperatures from a file (2 columns, 12 rows) and generating some functions to calculate certain the averages, highest, lowest (see code). NOTE: First column are highs, second column are lows.
void getData(int listTemp[rows][cols])
{
int r; //for rows
int c; //for columns
for (r = 0; r < rows; r++)
{
for (c = 0; c < cols; c++)
{
inData >> listTemp[c][r] >> listTemp[c][r];
}
}
}
It appears that you may have your rows and columns reversed. Look at how the array is shown in the function signature, and then look at how you're storing the values.
You should also stop using the global variables, make the variables local to a function then pass these variables to and from your functions as required.
Also, according to me your indexLowTemp and averageLow functions need editing as below resp.
1 2 3 4 5 6 7 8 9
void indexLowTemp(int listTemp[rows][cols]) {
int lowestIndex = listTemp[1][0];
for (int i = 0; i < rows; ++i) {
if (lowestIndex > listTemp[1][i]) {
lowestIndex = listTemp[1][i];
}
}
outData << "The index low temperature is " << lowestIndex << endl << endl;
}
1 2 3 4 5 6 7 8 9 10
void averageLow(int listTemp[rows][cols]) {
int lowSum = 0;
double lowAverage;
for (int i = 0; i < rows; ++i) {
lowSum = listTemp[1][i] + lowSum;
}
lowAverage = lowSum / rows;
outData << "Average low for the year: " << lowAverage << endl << endl;
}
Can you explain to me why we increment the lows and highs differently? I get the array setup, but I don't exactly know how (ie:[0][i], etc.) works. And I edited where I thought you guys were trying to correct me but I don't get the correct input.. Here's the updated code.
Edit: my global variables, if it's not good practice or if they shouldn't be there at all, where would I put them instead? I try to keep the code as light as possible but if you think I should move them and pass them by another means please explain to me how I would do that, I am a beginner after all :p
Yes the two global stream variables are a bad practice. Make them local to a function, getData() would probably be correct in this program, then pass them to the functions that require them.
Can you explain to me why we increment the lows and highs differently?
Look at your input file.
99 75
The high temperature is the first entry, the low temperature is the second entry. You could use two different arrays instead of the multidimensional array, it might be less confusing to you.
Part of your problem appears to be in this function:
1 2 3 4 5 6 7 8 9 10 11 12 13
void getData(int listTemp[rows][cols])
{
int r; //for rows
int c; //for columns
for (c = 0; c < cols; c++)
{
for (r = 0; r < rows; r++)
{
inData >> listTemp[c][r] >> listTemp[c][r];
}
}
}
You really shouldn't be using for() loops in this function. One simple while() loop should be adequate.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
int getData(int listTemp[rows][cols])
{
ifstream inData("tempsinput.txt");
if(!inData)
{ // The file opening failed, stop processing, return error code.
return -1;
{
int i = 0;
while(i < rows && inData >> listTemp[0][i] >> listTemp[1][i] )
{ // Don't forget to make sure you check that the array is in bounds.
++i;
}
// Return the number of lines actually read.
return i;
}
Note: instead of returning an error code you could throw an exception, if you've studied them. And in this version you don't open the file in main() and you don't need the global variables.
Well the point of this program was to help me understand multidimensional arrays better, so I appreciate the help :) but I was wondering if you could edit the entirety of the program to match the new int getData function you created.
edit: I was trying to avoid passing by value but it definitely doesn't hurt.
I was referring to the int function you changed from a void. Voids pass by reference while the int fx passes by value.. right? lol I'm constantly second guessing myself when it comes to this stuff.
The return type has nothing to do with pass by reference or pass by value. Both pass by reference and pass by value have to deal with the parameters not the return value of the function. You can pass variables by value, by reference, or by pointer no matter what you return.
I'm confused.. I'll paste what I have again and let me know where I'm going off tangent.. Did you completely replace int main() with int getData()? Which is why I'm asking about the inData/outData variables. Since I want to output some information about each function I call, do I only declare ifstream inData; ofstream outData; within a certain function and how do they pass around if I'm declaring them within a function besides main(). See where my confusion is coming from? Sorry if I'm not understanding you correctly..
#include <iostream>
#include <fstream>
#include <iomanip>
usingnamespace std;
constint cols = 2;
constint rows = 12;
int getData(int listTemp[rows][cols]);
int averageHigh(int listTemp[rows][cols]);
int averageLow(int listTemp[rows][cols]);
int indexHighTemp(int listTemp[rows][cols]);
int indexLowTemp(int listTemp[rows][cols]);
int main()
{
int listTemp[rows][cols];
getData(listTemp);
averageHigh(listTemp);
averageLow(listTemp);
indexHighTemp(listTemp);
indexLowTemp(listTemp);
system("pause");
return 0;
}
int getData(int listTemp[rows][cols])
{
ifstream inData("tempsinput.txt");
ofstream outData("tempsoutput.txt");
if (!inData)
{
return -1; //stop processing, error code
{
int i = 0;
while (i < rows && inData >> listTemp[0][i] >> listTemp[1][i])
{ //array within bounds
++i;
}
//return the number of lines actually read
return i;
}
}
outData << "The index low temperature is " << averageHigh(listTemp) << endl << endl;
outData << "The index low temperature is " << averageLow(listTemp) << endl << endl;
outData << "The index low temperature is " << indexHighTemp(listTemp) << endl << endl;
outData << "The index low temperature is " << indexLowTemp(listTemp) << endl << endl;
inData.close();
outData.close();
}
int averageHigh(int listTemp[rows][cols])
{
int highSum = 0;
int highAverage;
for (int i = 0; i < rows; i++) //increments through highs
{
highSum = listTemp[0][i];
}
highAverage = highSum / rows;
return highAverage;
}
int averageLow(int listTemp[rows][cols])
{
int lowSum = 0;
int lowAverage;
for (int i = 0; i < rows; ++i) //increments through lows
{
lowSum = listTemp[1][i];
}
lowAverage = lowSum / rows;
return lowAverage;
}
int indexHighTemp(int listTemp[rows][cols])
{
int highestIndex = 0;
for (int i = 0; i < rows; i++) //increments to find highest index
{
if (listTemp[0][i] > highestIndex)
{
highestIndex = listTemp[0][i];
}
}
return highestIndex;
}
int indexLowTemp(int listTemp[rows][cols])
{
int lowestIndex = listTemp[1][0];
for (int i = 0; i < rows; ++i) //increments to find lowest index
{
if (lowestIndex > listTemp[1][i])
{
lowestIndex = listTemp[1][i];
}
}
return lowestIndex;
}
You inData() doesn't look like the function I suggested. You need to be much more careful about your brace placement. And in C++ you don't need to call the close function. The class destructor will do this when the class goes out of scope.
Why did you add all that output stuff to an input function? You should strive to have your functions do as little as possible. The getData() function should only be getting the data from the file and filling in the array values.
It would be better if you created another function to do the output.
And in main() you should check save that return value.
1 2 3
int numElements = getData(listTemp);
if(numElements < 1) // Check to see that you actually read something from the file.
return numElements;
Also you should be using that return value in all of the other functions.
1 2 3 4 5 6 7 8 9 10 11 12
int averageHigh(int listTemp[rows][cols], int numberOfElemets);
...
averageHigh(listTemp, numElements);
...
int averageHigh(int listTemp[rows][cols], int numElements)
{
int highSum = 0;
int highAverage;
for (int i = 0; i < numElemets; i++) // notice the change here.
...
highAverage = highSum / numElemets; // Notice the change here.
Wouldn't I need brackets around: if (numElements < 1){ return numElements; } ?
And the question I had about the input/output files, I'm using visual studio 2015 and it gives me errors if I only define them within that getData() function. So I was wondering why I wouldnt globalize those and what my alternative would be. I've used fstream plenty before but not within different functions like this.
Also, creating that int numOfElements was a huge help..
edit: int numElements = getData(listTemp);
^
too few arguments
Wouldn't I need brackets around: if (numElements < 1){ return numElements; } ?
Technically, no, you don't need them, if the conditional block is only a single statement. But I'd recommend using them anyway, because it reduces the risk of introducing errors if you ever want to add more statements to the block.