I am trying to expand on previous code by implementing 2D-array's, however I keep getting issues with the console not outputting the correct values. The console is not taking in the right values when calculating the average and outputs 0 instead of the expected value. When running the code, the section where it would display the High and the Low scores would always display the first number that was typed in.
There are restrictions to work under.
Adjust the logic to drop the high score and the low score and average the remaining three scores for each student. The student grade is based on the average of the 3 middle scores.
All data is read in from the keyboard.
Two global constants may be utilized: one for the number of students and one for the number of tests.
Display in a table format the student's name, 5 test scores, average, and grade. Include a header in the table to label each column respectively.
Use iomanip and setw() to format the output.
Main should consist of variable declarations and function calls. This means the for loops to process the arrays resides in the functions, not in main.
Has to follow the base code.
`
using namespace std;
const int SCORES = 5;
const int NUM_STUDENTS = 3;
int main()
{
string name[NUM_STUDENTS];
int test[NUM_STUDENTS][SCORES];
char grade[NUM_STUDENTS];
float avg{};
int total = 0;
int hiIndex{}, loIndex{};
calcData(name, test, grade, total, hiIndex, loIndex, avg);
//display results
displayResults(name, test, grade, avg, loIndex, hiIndex);
system("pause");
return 0;
}
void calcData(string name[], int test[][SCORES], char grade[], int total, int hiIndex, int loIndex, float& avg)
{
for (int counter = 0; counter < NUM_STUDENTS; counter++)
{
getInput(name, test, counter, total);
cin.ignore();
//find index of the highest score and lowest score
findHiAndLow(test, hiIndex, loIndex, counter);
//assign letter grade
assignGrade(avg, grade, counter);
//calculate the class average
calcAvg(total - (test[counter][hiIndex] + test[counter][loIndex]), avg, SCORES - 2);
}
}
void getInput(string arrOne[], int arrTwo[][SCORES], int size, int& t)
{
//get student name
cout << "Input the student name and press enter\n";
getline(cin, arrOne[size]);
for (int i = 0; i < SCORES; i++)
{
//get student test score
cout << "Input the score for the midterm test\n";
cin >> arrTwo[size][i];
//(accumulate scores) total of all scores
t += arrTwo[size][i];
}
cout << endl;
}
int findHiAndLow(int t[][SCORES], int& h, int& l, int row)
{
for (int i = 0; i < SCORES; i++)
{
if (t[row][h] < t[row][i])
h = row;
if (t[row][l] > t[row][i])
l = row;
}
return h, l;
}
float calcAvg(int t, float a, int size)
{
a = static_cast<float>(t) / size;
return a;
}
void displayResults(string n[], int t[][SCORES], char g[], float a, int low, int high)
{
for (int counter = 0; counter < NUM_STUDENTS; counter++)
{
cout << left << setw(10) << n[counter] << ":";
for (int i = 0; i < SCORES; i++)
{
cout << setw(10) << t[counter][i];
}
cout << endl;
}
cout << "\n\nThe class average for this test = " << a << endl << endl;
for (int i = 0; i < NUM_STUDENTS; i++)
{
cout << n[i] << " your highest test score = " << t[i][high] << endl;
cout << n[i] << " your lowest test score = " << t[i][low] << endl << endl;
}
}
`
The expected outcome was for the program to take the average of the 3 middle scores that are left after dropping both the high and low scores from the initial 5 scores that are given. I have tried rearranging the values in both findHiandLow() and getInput(). I have tried having both for loops for getInput() within the function and have switched back to having one on the outside (within calcData()) to include the other functions, with the intent of having it loop for each student.
I wanted the console to print out the average of the three middle scores and not include the High and low, I was also expecting the console to print out the High and low scores for the student but it only prints the first score.
If my numbers were, for example, 12, 89, 45, 100, 23; The expectation would've been that it would drop the 12 and 100 and leave me with 89, 45, and 23. It would then take the average of those 3 numbers which in theory should result in 52.34 and result in an "F", however it prints out 0. and because the number that was first typed in was 12 the lowest and highest number would be listed as 12. It should have been 12 and 100 respectively.
This is another case of the incredibly common newbie confusion over returning values from functions.
This is your function
float calcAvg(int t, float a, int size)
{
a = static_cast<float>(t) / size;
return a;
}
You are trying to calculate the average and return the result, but for some reason you have declared a as a parameter, instead of as a local variable. This is how it should look
float calcAvg(int t, int size)
{
float a = static_cast<float>(t) / size;
return a;
}
Once you see that you should see that it can be further simplified, eliminating a altogether
float calcAvg(int t, int size)
{
return static_cast<float>(t) / size;
}
Now look at how you call calcAvg.
calcAvg(total - (test[counter][hiIndex] + test[counter][loIndex]),
avg, SCORES - 2);
you are calling the function, but doing nothing with the returned value. This is how it should look
avg = calcAvg(total - (test[counter][hiIndex] + test[counter][loIndex]),
SCORES - 2);
Now the return value of calcAvg is being assigned to the variable avg changing it's value. This is clearly what you intended. If you want to change the value of a variable using a functions return value the syntax is x = func(); not func(x).
Really not sure why this is such a stumbling block for newbies. The correct code has always seemed natural and straightforward to me. But, in any case, remember that parameters and return values are different things, with different syntax, and different purposes.
Related
I am new to C++, but this picture here is the goal of my program.
This is what I need my input/output to look like:
--- INPUT ---
The first line of standard input contains an integer 1 ≤ C ≤ 50, the number of test cases.
C data sets follow. Each data set begins with an integer, N, the number of people in the class (1 ≤ N ≤ 1000).
N integers follow, separated by spaces or newlines, each giving the final grade (an integer between 0 and 100) of a student in the class.
--- OUTPUT ---
For each case you are to output a line giving the percentage of students whose grade is above average, rounded to exactly 3 decimal places.
This is the code that I currently have:
#include <iomanip>
#include <iostream>
#include <numeric>
#include <string>
#include <vector>
using std::vector;
void aboveAverage(int testCases) {
// initialize number of students for vector size
int numOfStudents;
// initialize a vector to hold grades
vector<int> grades;
// for # of testCases, recieve # of students per test case
for(int i = 0; i < testCases; i++) {
std::cout << "Num of Students: ";
std::cin >> numOfStudents;
// per test case, recieve grade per student and push into vector
for(int j = 0; j < numOfStudents; j++) {
int grade1;
std::string grade;
// debug statement
std::cout << "Enter grades: ";
std::getline(std::cin, grade);
grade = int(grade1);
grades.push_back(grade1);
}
}
// sum the vector array and intitialize above average threshold
int sum = std::accumulate(grades.begin(), grades.end(), 0);
// debug statement
std::cout << "Sum = " << sum << std::endl;
int threshold = sum / numOfStudents;
// initialize a counter and based on threshold get the # of elements that
// meet that criteria
int counter = 0;
for(int j = 0; j < numOfStudents; j++) {
// if the grade is larger than the threshold, add to counter
if(grades[j] > threshold) {
counter += 1;
}
}
// get the percentage of those above average and print it out
float percentage = (counter / numOfStudents) * 10;
std::cout << std::setprecision(3) << std::fixed << percentage << std::endl;
}
int main() {
int testCases;
// debug statement
std::cout << "# of Test Cases: ";
std::cin >> testCases;
aboveAverage(testCases);
return 0;
}
The code as a whole runs "fine", I guess you could say. Just no errors in the compiler that yell at me at least. I just cannot, for the life of me, figure out how to set it up exactly like it should for the input. I think I complicated my life with the vector, although it seems easier to me this way. I think I'm close. Hopefully I am!
#include <iostream>
using namespace std;
// prototype functions
void DisplayResult(float MaxOrMin);
float FindMinimum(float Array[5]);
float FindMaximum(float Array[5]);
//Global Variables
float Array[5];
float MaxOrMin = 3;
float FindMin;
float FindMax;
//Main Function
int main()
{
cout << "Please enter 5 numbers: " << endl;
for (int i=0; i<5; i++)
{
cin >> Array[i]; // input for array
}
cout << "Please enter '0' for minimum or '9' for maximum:" << endl;
cin >> MaxOrMin; // input 0 or 9 for min or max
//Calling Functions
FindMinimum(Array);
FindMaximum(Array);
DisplayResult(MaxOrMin);
return 0;
}
//Function to find Minimum
float FindMinimum(float Array[5])
{
float FindMin = Array[0];
for (int y=1;y<5;y++)
{
if(Array[y] < FindMin)
FindMin = Array[y];
}
return FindMin;
}
//Function to find Maximum
float FindMaximum(float Array[5])
{
float FindMax = Array[0];
for (int x=1;x<5;x++)
{
if(Array[x] > FindMax)
FindMax = Array[x];
}
return FindMax;
}
This last part is my if, else if, else funtion:
//Function to display minimum or maximum result
void DisplayResult(float MaxOrMin)
{
if (MaxOrMin == 0)
cout << "Minimum is: " << FindMin << endl;
else if (MaxOrMin == 9)
cout << "Maximum is: " << FindMax << endl;
else
cout << "Invalid Input" << endl;
}
My project is to create a program using functions to take user input on a 5 float array. Then find the max and min and display whichever the user asks for.
Here is where my problem comes in. For both max(input 9) and min(input 0) I am getting "0". However any other input correctly returns my "Invalid Input" message.
I'm not getting any errors or warnings or errors at all on eclipse. My professor has told me that my problem was likely with my void function for displaying results. I am hoping someone could point me in the right direction here.
Apologies for my formatting and/or if this question is too basic for this site.
You misunderstand how local and global variables work. Your Find* functions shadow the globals with locals and thus they don't appear to do anything.
The problem is that your FindMinimum() (and the same with FindMaximum()) function compute the minimum (maximum) in a local variable and return it but you, in main() don't receive they in correct variables
So the computed value is lost.
I mean... instead of
FindMinimum(Array);
FindMaximum(Array);
you should write
FindMin = FindMinimum(Array);
FindMax = FindMaximum(Array);
#include <fstream>
#include <iostream>
#include <cstdlib>
using namespace std;
const int NUMBER = 20;
void dataRead(double a[], int size, double& data);
double averageArray(const double a[], double data);
double totalArray(const double a[], double data);
double highCost(const double a[], double data);
double lowCost(const double a[], double data);
int main()
{
// Calling in the file
ifstream in;
char in_file[16];
double data;
double averageSales, higherSale, lowerSale, totalSales, salesData[NUMBER];
cout << "Enter the input file name." << endl;
cin >> in_file;
in.open(in_file);
// Incase the file doesnt open
if(in.fail())
{
cout << "File not found." << endl;
exit(1);
}
// For calling the answers from the formula functions
totalSales = totalArray(salesData, data);
cout << endl << "The total sales are $" << totalSales << endl;
averageSales = averageArray(salesData, data);
cout << "The average sales amount is $" << averageSales << endl;
higherSale = highCost(salesData, data);
cout << "The highest sales amount is $" << higherSale << endl;
lowerSale = lowCost(salesData, data);
cout << "The lowest sales amount is $" << lowerSale << endl;
return 0;
}
// Formula functions used for values
double totalArray(const double sales[], double n)
{
double sum = 0;
for(int count = 0; count < n; count++)
sum += sales[count];
return(sum);
}
double averageArray(const double sales[], double n)
{
return((double)totalArray(sales, n));
}
double highCost(const double sales[], double n)
{
double highest;
highest = sales[0];
for(int count = 1; count < n; count++)
if(highest < sales[count])
highest = sales[count];
return(highest);
}
double lowCost(const double sales[], double n)
{
double lowest;
lowest = sales[0];
for(int count = 1; count < n; count++)
if(lowest > sales[count])
lowest = sales[count];
return(lowest);
}
void readData(int a[], int size, double& data)
{
}
I am having trouble getting my program to read files and calculate the data for answers.. It is supposed to take in a file and return specific values pertaining to what is in the file. Like the average, highest cost value, lowest cost value, and total values together. I am compiling this on c9.io and when I added a new file to grab the information from no matter what values I put in the file it just gives me zeros or weird numbers with remainders. Would appreciate some guidance! Thank you!
You open the file, but never read anything from it (nor close it, for that matter). You read from in in a similar way that you read from in, and this describes how to close: How to close IStream?.
I don't see a line that would actually read the data in the file, you're just opening it.
How to read the contents of a file
If your file has just plain numbers and whitespace in it, like "69 10 38 33 (...)", you'll want to read them like that:
int number;
file>>number;
cout<<number<<endl;
file>>number;
cout<<number<<endl;
- the example program will output the following:
69
10
When your file is written to be more "human-readable", like:
Value1 - 69
Value2 - 10
etc.
it gets tricky. I would recommend just changing the file to the " 69 10 ..." format. If you really want to keep it like that, you could read the values to a string - just as you would with numbers - and check if it's numerical. If yes, convert it to an int using stringstream. These 2 functions may help you
#include <sstream>
int StringToInt(string input)
{
int res;
stringstream ss(input);
ss>>res;
return res;
}
bool IsNumeric(string input)
{
for(int i=0; i<input.size(); i++)
{
if(input[i] < '0' && input[i] > '9')
return false;
}
return true;
}
And by the way: you can't pass arrays to a function like you tried to do.
So I'm trying to write a basic program in C++ to get the cost of something, the quantity, and calculate the total/subtotal, in three different functions, then display it in main().
Problem is, the variables aren't making it out of the function and I don't know why. I've put output statements inside the functions themselves to check, and the problem only seems to be when I'm trying to pull them out of said functions.
#include <iostream>
using namespace std;
int price(int cost)
{
cout << "What is the cost of the robot?" << endl;
cin >> cost;
if (cost < 1000) //validation
{
cout << "Cost is too low. Setting to $1000." << endl;
cost = 1000;
return cost;
}
return cost;
}
int numRobots(int number)
{
cout << "How many robots are being ordered?" << endl;
cin >> number;
if (number < 50) //validation
{
cout << "We only sell in quantities of 50 or more. Setting quantity to 50." << endl;
number = 50;
return number;
}
return number;
}
void grandTotal(int cost, int number, double &subtotal, double &total)
{
subtotal = (cost * number);
total = (subtotal * .07) + subtotal;
}
int main()
{
int cost = 0;
int number = 0;
double subtotal = 0;
double total = 0;
price(cost);`enter code here`
numRobots(number);
grandTotal(cost, number, subtotal, total);
cout << cost; //testing
cout << number; //outputs
cout << total; //of
cout << subtotal; //variables
system("pause");
return 0;
price(cost);
You are calling a function which returns an int, but you're not storing the int anywhere. You might want to go back to your text book and check the chapter on functions, and how they work. No offense but this is rather basic.
You're doing the same thing with numRobots.
Alternatively, you could pass the parameter by reference and modify it, but imo, that's less easy to understand.
tl;dr;
You should be doing int cost = price(); (there's no reason for the function to take an int as a parameter)
Use returned value or pass parameter by reference or pointer.
1.
int result = numRobots(number);
2.
int numRobots(int& number) {.....}
You need to pass the variables by reference:
int cost = 0;
int number = 0;
price(cost);
numRobots(number);
void price(int& cost)
{
....
}
void numRobots(int& number)
{
....
}
Note the void return type in this case!
Alternatively, you can utilize the return value:
int cost = price(cost);
int number = numRobots(number);
But this method doesn't make much sense because the variable passed as parameter to methods is the same as the one in which the return value is stored!
I'm really confused. I have to make this lab for a class and I can't seem to have the search only display one result but all of the months of the year. I also can't seem to figure out why its not displaying the TotalRainfall when I input 0 into the month of the year.
Thank you.
#include <iostream>
#include <fstream>
const int MaxSize = 12; //How many weather lines will be available.
using namespace std;
struct WeatherInformation
{
int Month; //Months of the year
float TotalMonthsRainfall; //Total amount of rainfall
float HighTemp; //The Highest temperature of the month.
float LowTemp; //The Lowest temperature of the month.
float AverageTemp; //The Average temperature of the month.
};
WeatherInformation WeatherArray[MaxSize]; //Declaring a month array of MaxSize
void ReadFile(ifstream& MyinFile, WeatherInformation WeatherArray[]);
void WeatherMonthSearch (WeatherInformation WeatherArray[]);
int main()
{
float TotalRainfall = 0;
int count = 1; //Counts how many times the for loop goes.
int MonthOfWeather; //User input of the month.
char ProgramRedo; //User input if they want to reuse the program.
char exit_char; //User input to exit the program.
ifstream MyinFile; //Variable that uses file.
ReadFile (MyinFile, WeatherArray); //Call ReadFile Function
WeatherMonthSearch (WeatherArray); //Call WeatherMonthSearch Function
MyinFile.close(); //Closes file.
}
//Brett Holmes
//4/30/2013
//PreCondition:You need a file labeled weather.dat
//PostCondition: It puts the file variables into an array.
void ReadFile(ifstream& MyinFile, WeatherInformation WeatherArray[])
{
float TotalRainfall = 0;
char exit_char;
int count = 0;
int Month = 0;
cout << "Your Weather Machine" << endl << endl;
MyinFile.open("weather.dat");
if (!MyinFile)
{ //no
cout << "Can't open input file." << endl; //Tests the right file.
char exit_char; //End Program
cout << "Press any key to exit" << endl;
cin >> exit_char;
}
for(count = 1; count < MaxSize; count++) //Puts the file variables in the array.
{
WeatherArray[count].Month = WeatherArray[count].Month + 1;
MyinFile >> WeatherArray[count].TotalMonthsRainfall;
MyinFile >> WeatherArray[count].HighTemp;
MyinFile >> WeatherArray[count].LowTemp;
(WeatherArray[count].AverageTemp = ((WeatherArray[count].HighTemp + WeatherArray[count].LowTemp)/2));
(TotalRainfall = TotalRainfall + WeatherArray[count].TotalMonthsRainfall);
}
}
//Brett Holmes
//4/30/13
//PreCondition:You need to have the months already put into an array in a struct.
//PostCondition:Outputs the rainfall stats the user puts in then asks to run again.
//Outputs a error message if they type in the month wrong.
void WeatherMonthSearch (WeatherInformation WeatherArray[])
{
float TotalRainfall;
int months;
int MonthOfWeather;
char ProgramRedo;
do
{
bool MonthFound = false;
cout << "Please input the number of the Month. Ex. 1=Jan. 2=Feb. etc \n\n";
cin >> MonthOfWeather;
for(int i = 1; i <= MaxSize; i++)
{
months = WeatherArray[i].Month;
if(months == MonthOfWeather ) //Finds the artist and outputs the results
{
cout << "\nTotal Months Rainfall: " << WeatherArray[i].TotalMonthsRainfall << " \n";
cout << "Highest Temperature: " << WeatherArray[i].HighTemp << " \n";
cout << "Lowest Temperature: " << WeatherArray[i].LowTemp << " \n";
cout << "Average Temperature: " << WeatherArray[i].AverageTemp << " \n";
MonthOfWeather = true;
}
}
if(MonthOfWeather == 0)
{
cout << "The total rainfall for the year is: " << TotalRainfall << ".";
}
if(MonthFound == false)
{
cout << "\nMonth Number error. Month not found. Try again.\n\n";
MonthOfWeather = false;
}
cout << "Would you like to look up another month of weather?\n";
cout << "Enter a 'Y' if yes and 'N' if no.\n";
cin >> ProgramRedo;
}while(ProgramRedo == 'Y');
}
Several obvious problems:
Arrays in C++ is 0-based, so your for loop is off-by-one. In your search function, for(int i = 1; i <= MaxSize; i++) should be for(int i = 0; i < MaxSize; i++). Similarly, in your read function, for(count = 1; count < MaxSize; count++) should be for(count = 0; count < MaxSize; count++) (If you want to skip index 0 because you are using it as a signal value, then you should set MaxSize to 13 and have the loop start at 1.)
Why are you assigning a boolean to MonthOfWeather? Do you mean MonthFound?
You read function is not setting the months correctly. WeatherArray[count].Month = WeatherArray[count].Month + 1; should be WeatherArray[count].Month = count; if you are using a 1-based loop or WeatherArray[count].Month = count + 1; if the loop is 0-based.
You calculated your total rainfall in the read function, but the result is stored in a local variable so it's lost when the read is done. Either make TotalRainfall a global variable or do your calculations in your search function.
There are a lot of redundant variable definitions: for example, your weather data array is a global so there is no reason to actually pass it around; exit_char is declared twice in your read function; the first five lines of your main() declared variables that you never used.
Also, your read function does not actually exit the program on failure - it even still attempts to read from the stream and then call your search function! If error-checking is a requirement, you should either have the read function return a boolean and check that the read function succeeded before calling your search function, or simply call std::exit after that cin >> exit_char;.
So, one problem you have is that you have local variables that appear in multiple places, but appears like you expect them to actually contain the same information.
For example, I see three different TotalRainFall. One in main, which is just there, not used for anything, one in ReadFile which is calculated, and one in WeatherMonthSearch, which is not set to anything.
I suspect you want all three of these to actually do something. One way to achieve that would be to remove the local ones in ReadFile and WeatherMonthSearch, and instead pass in the one from main (as a reference into ReadFile).
There's also a few places where you use variables without initializing them. Make it a habit to initialize EVERYTHING and EVERYWHERE!
Enable warnings in your compiler - if you have any form or reasonably new compiler (gcc or MS Visual Studio of recent vintage), it should tell you at least some of these things.