C++ While loop and Array - c++

I have made a application where you enter in all the marks and it gives you the average and also makes it repeat itself but the problem is that
1) when ever the 'Finding average' line is executed, it gives me the
wrong value and also I use array to do so.
2)When ever I try to
iterate the application, the destructor is called and messes up my
application
and here is my code
#include <iostream>
#include <string>
using namespace std;
class Grade{
private:
int* ptr;
int number;
public:
Grade(const int hNumber){
number = hNumber;
ptr = new int[this->number];
}
Grade(const Grade& cpy){
ptr = new int[cpy.number];
}
void get_marks(){
for(int i = 0; i < number; ++i){
cout << "Enter Mark " << i << ": ";
cin >> ptr[i];
}
}
const int& operator [](const int access) const{
return ptr[access];
}
~Grade(){
cout << "Deleting memory" << endl;
delete [] ptr;
}
};
int main(){
//local variables
int sum = 0;
string name,subject;
int repeat;
char again = 'y';
//user interface
cout << "Welcome to Grade Marker" << endl;
cout << "Enter your name: ";
getline(cin,name);
while(again == 'y'){
cout << "Enter the subject name: ";
getline(cin,subject);
cout << "How many marks are being entered: ";
cin >> repeat;
//creating instance of grade
Grade grd(repeat);
grd.get_marks();;
//display info
cout << "The average mark is: ";
for (int i = 0; i < repeat; i++){
sum = ((sum + grd[i]) / repeat);
}
cout << sum << endl;
//looping the application
cout << "Would you like to enter another subject[y/n]: ";
cin >> again;
}
//good bye message
if (again == 'n' || again == 'no'){
cout << "Goodbye" << endl;
}
system("pause");
return 0;
}
and just to make it simple, the code section which I think gives me error are
cout << "Would you like to enter another subject[y/n]: ";
cin >> again;
}
//good bye message
if (again == 'n' || again == 'no'){
cout << "Goodbye" << endl;
}
and
//display info
cout << "The average mark is: ";
for (int i = 0; i < repeat; i++){
sum = ((sum + grd[i]) / repeat);
}
cout << sum << endl;
and thank you for your time

You are doing integer division, and in addition you do not reinitialize sum to 0 for each iteration. You can move sum declaration inside of the loop and just write:
float sum = 0;
for (int i = 0; i < repeat; i++){
sum += grd[i];
}
cout << "The average mark is: ";
cout << sum / repeat << endl;

std::cin.ignore() will help you here.
Adding...
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
...to the very end of your while-loop will clear out the input buffer up to the newline... You'll find that this will end the seemingly infinite loop.
See How do I flush the cin buffer? for more info.

Your while loop is calling the destructor because of scope. You are declaring the Grade grd every iteration you run the while loop. That means that your grd from the previous iteration is being redeclared again and again, hence the destructor being called. But that's normal. Did you want to save the Grade instances? In that case you'll need to make an array of Grade objects

Related

Output does not include all input for my array

I have this program that is barely started:
#include <iostream>
#include <iomanip>
#include <ctime>
#include <string>
using namespace std;
class Grade
{
public:
string studentID;
int userChoice = 0;
int size = 0;
double* grades = new double[size]{0};
};
void ProgramGreeting(Grade &student);
void ProgramMenu(Grade& student);
string GetID(Grade& student);
int GetChoice(Grade& student);
void GetScores(Grade& student);
int main()
{
Grade student;
ProgramGreeting(student);
ProgramMenu(student);
}
// Specification C1 - Program Greeting function
void ProgramGreeting(Grade &student)
{
cout << "--------------------------------------------" << endl;
cout << "Welcome to the GPA Analyzer! " << endl;
cout << "By: Kate Rainey " << endl;
cout << "Assignment Due Date: September 25th, 2022 " << endl;
cout << "--------------------------------------------" << endl;
GetID(student);
cout << "For Student ID # " << student.studentID << endl;
}
void ProgramMenu(Grade &student)
{
cout << "--------------------------------------------" << endl;
cout << setw(25) << "Main Menu" << endl;
cout << "1. Add Grade " << endl;
cout << "2. Display All Grades " << endl;
cout << "3. Process All Grades " << endl;
cout << "4. Quit Program." << endl;
cout << "--------------------------------------------" << endl;
GetChoice(student);
}
string GetID(Grade &student)
{
cout << "Enter the student's ID: ";
cin >> student.studentID;
if (student.studentID.length() != 8) {
cout << "Student ID's contain 8 characters ";
GetID(student);
}
return student.studentID;
}
int GetChoice(Grade &student)
{
cout << "Enter your selection: ";
cin >> student.userChoice;
if (student.userChoice == 1) {
GetScores(student);
}
else if (student.userChoice == 2)
{
}
else if (student.userChoice == 2)
{
}
else if (student.userChoice == 4)
{
exit(0);
}
else
{
cout << "Please enter 1, 2, 3 or 4" << endl;
GetChoice(student);
}
}
void GetScores(Grade &student)
{
int count = 0;
double score = 0;
cout << "How many test scores would you like to enter for ID# "
<< student.studentID << "? ";
cin >> student.size;
while (count != student.size) {
cout << "Enter a grade: ";
cin >> score;
for (int i = 0; i < student.size; i++) {
student.grades[i] = score;
}
count++;
}
for (int i = 0; i < student.size; i++) {
cout << student.grades[i] << " ";
}
}
I am trying to make sure my array is recording all test scores, but when I output the array in my GetScore function, each element in the array is the same or equal to the last score I entered. For example, if I choose 3 for size and then enter three values of 99.2 86.4 90.1, all three elements will read 90.1.
Why is this happening?
Your Grade class is allocating an array of 0 double elements (which is undefined behavior), and then your GetScores() function does not reallocate that array after asking the user how many scores they will enter, so you are writing the input values to invalid memory (which is also undefined behavior).
Even if you were managing the array's memory correctly (ie, by using std::vector instead of new[]), GetScores() is also running a for loop that writes the user's latest input value into every element of the array, instead of just writing it to the next available element. That is why your final output displays only the last value entered in every element. You need to get rid of that for loop completely.
Try something more like this instead (there are several other problems with your code, but I'll leave those as separate exercises for you to figure out):
class Grade
{
public:
...
int size = 0;
double* grades = nullptr;
};
...
void GetScores(Grade &student)
{
int size = 0;
double score = 0;
cout << "How many test scores would you like to enter for ID# " << student.studentID << "? ";
cin >> size;
if (student.size != size) {
delete[] student.grades;
student.grades = new double[size]{0};
student.size = size;
}
for(int i = 0; i < size; ++i) {
cout << "Enter a grade: ";
cin >> score;
student.grades[i] = score;
}
for (int i = 0; i < size; ++i) {
cout << student.grades[i] << " ";
}
}
Alternatively:
#include <vector>
...
class Grade
{
public:
...
vector<double> grades;
};
...
void GetScores(Grade &student)
{
size_t size = 0;
double score = 0;
cout << "How many test scores would you like to enter for ID# " << student.studentID << "? ";
cin >> size;
student.grades.resize(size);
for (size_t i = 0; i < size; ++i) {
cout << "Enter a grade: ";
cin >> score;
student.grades[i] = score;
}
/* alternatively:
student.grades.clear();
for (size_t i = 0; i < size; ++i) {
cout << "Enter a grade: ";
cin >> score;
student.grades.push_back(score);
}
*/
for (size_t i = 0; i < size; ++i) {
cout << student.grades[i] << " ";
}
}
I removed my for loop from my while loop.
void GetScores(Grade &student)
{
int count = 0;
double score = 0;
cout << "How many test scores would you like to enter for ID# "
<< student.studentID << "? ";
cin >> student.size;
while (count != student.size) {
cout << "Enter a grade: ";
cin >> score;
student.grades[count] = score;
count++;
}
for (int j = 0; j < student.size; j++) {
cout << student.grades[j] << " ";
}
}

Looping Confusion

My code seems to ask twice instead of once if I want to run the code again. I just want it to run normally like my other cases which only ask once after I have viewed the activity and these two activities are the only ones with problems. What seems to be the problem here:
case 5:
cout<<"Here are the list of activities in Activity 5:" << endl;
cout<<"[5.1]Determining a Number within the Array" << endl;
cout<<"[5.2]Determining the Highest and Lowest integer" << endl;
cout<<"[5.3]Reversed Array" << endl;
cin >> choice;
system("CLS");
if(choice == 5.1){
counter +=1;
int nos[10];
int det;
cout <<"Note: Do not input any decimal numbers." << endl;
for(int array = 1; array < 11; array++){
cout << "Input integers 1-10 only. [" << array << "]";
cin >> nos[det];
}
cout << "Type in 1 integer value only.[" << det << "]";
cin >> det;
if(det >= nos[1] || det <= nos[10]){
cout << "The value is within the scope of the array.";
}
else{
cout << "The value is not within the scope of the array.";
}
system ("PAUSE");
system ("CLS");
cout << "Do you want to run the program again? (y/n)" << endl;
cin >> choose;
}
else if(choice == 5.2){
counter +=1;
cout <<"Note: Do not input any decimal numbers." << endl;
cout <<"Enter your integers." << endl;
int nos[10];
int put;
for(int rep = 1; rep < 11; rep++){
cout <<"[" << rep << "]";
cin >> nos[rep];
}
int highnos = nos[1];
int lownos = nos[1];
for(int rep = 1; rep < 11; rep++){
if(nos[rep] > highnos){
highnos = nos[rep];
}
}
cout << "Your highest integer is:" << highnos << endl;
for(int rep = 1; rep > 11; rep++){
if(nos[rep] < lownos){
lownos = nos[rep];
}
}
cout <<"Your lowest integer is:"<< lownos << endl;
system ("PAUSE");
system ("CLS");
cout << "Do you want to run the program again? (y/n)" << endl;
cin >> choose;
}
P.S. my activities also has errors but dont mind it :D
First of all, you haven't initialized anything so everything is taking garbage values.
initialize det first and if you want to input the whole array then run a loop. cin>>nos[det] only inputs one value at a garbage index according to your code.
This code is a mess. Kindly fix initializations and inputs, then share the output you're getting vs the output you want.

C++ : Making a do while loop repeat

I'm very sorry for the super newbie question, but I cannot for the life of me understand how to make a do while loop repeat. I changed a while loop into a do while loop and now I don't know how to get it to ask "would you like to repeat Y or N?" any explanation?
I've read various posts that accomplish a do while loop repeat, but they don't make sense to me.
Am I essentially going to wrap this code into another do while loop? Do I move the boolean expression to before the while?
#include <iostream>
using namespace std;
int main(void)
{
int x;
int count = 0;
int N;
double sum = 0;
double average;
char ans;
{
cout << "Enter number of values, N, to be read in <Enter>:" << endl;
cin >> N;
do
{
cout << "\n Enter a grade <Enter>: ";
cin >> x;
sum = sum + x;
count++; //
} while (count < N);
if (N == 0)
cout << "You have entered 0 numbers. No average will be computed. Bye! \n";
else {
average = average = sum / N;
cout << "The average of these " << N << " grades is " << average << endl;
}
cout << "Would you like to enter more values to calculate your grade average?\n";
system("pause");
return 0;
}
}
can do this:
char repeat='y';
cout << "Enter number of values, N, to be read in <Enter>:" << endl;
cin >> N;
do
{
for(int i=0;i<n;i++){
cout << "\n Enter a grade <Enter>: ";
cin >> x;
sum = sum + x;
count++; //
}
if (N == 0)
cout << "You have entered 0 numbers. No average will be computed. Bye! \n";
else {
average = average = sum / N;
cout << "The average of these " << N << " grades is " << average << endl;
}
cout << "Would you like to enter more values to calculate your grade average?\n";
cin>>repeat;
}while(repeat=='y');
May be this is what you need, with char YorN you are considering if to continue or break the inner do-while.
#include <iostream>
using namespace std;
int main(void)
{
int x;
int count = 0;
int N;
double sum = 0;
double average;
char ans;
char YorN;
do{
cout << "Enter number of values, N, to be read in <Enter>:" << endl;
cin >> N;
do
{
cout << "\n Enter a grade <Enter>: ";
cin >> x;
sum = sum + x;
count++; //
} while (count < N);
if (N == 0)
cout << "You have entered 0 numbers. No average will be computed. Bye! \n";
else {
average = average = sum / N;
cout << "The average of these " << N << " grades is " << average << endl;
}
cout << "Would you like to enter more values to calculate your grade average?\n";
cin>>YorN;
} while (YorN=='Y');
return 0;
}
Although there are a ton of ways to do it better, this code allows me to explain what is happening. Do-While loops are definitely pretty tricky. However, just remember that a do-while loop is designed to run at least once.
In the case of our code, we set up if statements to test against running code where it is not appropriate.
Take a look at how the very first if statement is N > 0, the if-statement does execute, please do not forget that. Once more for emphasis, the if statement DOES execute, it just results in false.
With that being said, you use a do-while loop when you want your code block to execute AT LEAST once. Notice how our while statement has two things we're testing for, one, is the answer 'Y' from the user to continue, and if it is, is the newly inputted N value greater than 0?
You might be wondering if the inner most if statement ever executes at least once, well the answer is it depends on the previous if statement result if(N > 0) and if(count == N && N != 0) both execute once every single time the while loop stays true. However that nested if depends on it's parent result.
I hope this cleared some things up for you on do-while loops.
#include <iostream>
using namespace std;
int main(void)
{
int x;
int count = 0;
int N;
double sum = 0;
double average;
char ans = 'Y';
cout << "Enter number of values, N, to be read in <Enter>:" << endl;
cin >> N;
do
{
if(N > 0){ //THIS IF STATEMENT WILL ALWAYS RUN AT LEAST ONCE
cout << "\n Enter a grade <Enter>: ";
cin >> x;
sum = sum + x;
count++;
}
if(count == N && N != 0) {//THIS IF STATEMENT WILL ALSO ALWAYS RUN AT LEAST ONCE
average = average = sum / N;
cout << "The average of these " << N << " grades is " << average << endl;
cout << "Would you like to enter more values to calculate your grade average?\n";
cin>>ans;
if(ans == 'Y') {//This one depends on it's parents result.
x = 0;
N = 0;
sum = 0;
count = 0;
cout << "Enter number of values, N, to be read in <Enter>:" << endl;
cin >> N;
}
}
} while (ans == 'Y' && N != 0);
if (N == 0)
cout << "You have entered 0 numbers. No average will be computed. Bye! \n";
system("pause");
return 0;
}

Confused about an exercise in my book

I need to be able to have the objects within the array be valid or invalid/ have value or have no value.
So if the user entered only 5 accounts out of 10 possible, it would throw away the last 5 that do not have any value what so ever, so as to not ask for a computed interest for an account that doesn't exist.
How do I do this?
#include <iostream>
#include <iomanip>
using namespace std;
class BankAccount
{
private:
int accountNum;
double accountBal;
static const double annualIntRate;
public:
void enterAccountData(int, double);
void computeInterest();
void displayAccount();
};
//implementation section:
const double BankAccount::annualIntRate = 0.03;
void BankAccount::enterAccountData(int number, double balance)
{
cout << setprecision(2) << fixed;
cout << "Enter the account number " << endl;
cin >> number;
accountNum = number;
while(number < 0 || number < 1000)
{
cout << "Account numbers cannot be negative or less than 1000 " <<
"Enter a new account number: " << endl;
cin >> number;
}
cout << "Enter the account balance " << endl;
cin >> balance;
accountBal = balance;
while(balance < 0)
{
cout << "Account balances cannot be negative. " <<
"Enter a new account balance: " << endl;
cin >> balance;
}
return;
}
void BankAccount::computeInterest()
{
const int MAX_ACCOUNTS = 10;
const int MONTHS_IN_YEAR = 12;
int months;
double rate = 0;
int counter = 0;
cout << endl << "How many months will the account be held for? " << endl;
cin >> months;
counter = 0;
do
{
accountBal = accountBal * annualIntRate + accountBal;
counter++;
}while(months > counter);
cout << endl << "Account # " << accountNum << " 's balance is:$" << accountBal << endl;
}
int main()
{
const int QUIT = 0;
const int MAX_ACCOUNTS = 10;
int counter;
int input;
int number = 0;
double balance = 0;
BankAccount accounts[MAX_ACCOUNTS];
//BankAccount display;
counter = 0;
do
{
accounts[counter].enterAccountData(number, balance);
cout << " Enter " << QUIT << " to stop, or press 1 to proceed.";
cin >> input;
counter++;
}while(input != QUIT && counter != 10);
for(counter = 0; counter < MAX_ACCOUNTS; counter++)
{
accounts[counter].computeInterest();
}
system("pause");
return 0;
}
You should try tonarrow down your questions to just what you are really asking, this is a little confusing to look at.
After the first loop, have it "remember" what value for counter it managed to reach, and then in the second loop only iterate up to that, instead of up to MAX_ACCOUNTS.
And converting from months to years is just dividing by 12 no?
It seems you have skipped the chapters about Arrays. Re-read it!
ps. surely 0 < 1000 while(number < 0 || number < 1000)
void BankAccount::enterAccountData(int number, double balance). What is the need for the two arguments ? Take the input directly for the member variables. Unnecessary operations are commented. This would also do the job -
void BankAccount::enterAccountData()
{
cout << setprecision(2) << fixed;
cout << "Enter the account number " << endl;
cin >> accountNum; // Take input directly to accountNum
// accountNum = number; // No need of this assignment
while(accountNum < 0 || accountNum < 1000)
{
cout << "Account numbers cannot be negative or less than 1000 " <<
"Enter a new account number: " << endl;
cin >> accountNum;
}
cout << "Enter the account balance " << endl;
cin >> accountBal;
// accountBal = balance; // Unnecessary assignment
while(accountBal < 0)
{
cout << "Account balances cannot be negative. " <<
"Enter a new account balance: " << endl;
cin >> accountBal;
}
// return; // What is the need of this return statement? Method signature says
// it doesn't return anything.
}
When you think of declaring variables, think of whether they are necessary. Unnecessary declaring and assigning the variables make the problem looks complex and is the source of confusion. Think simple :)

C++ 2d Array Class Function Call Help

I hope this question takes a simple fix, and I am just missing something very small.
I am in my second semester of C++ in college, and we are just getting into OOP. This is my first OOP program, and it is causing me a little problem. Here are the errors I am getting:
Member function must be called or its address taken in function displayGrid(int,Cell ( *)[20])
Member function must be called or its address taken in function Turn(int,int,Cell ( *)[20])
Member function must be called or its address taken in function Turn(int,int,Cell ( *)[20])
Warning: Parameter 'grid' is never used in function displayGrid(int,Cell ( *)[20])
Here is all of my code. I am aware It is much more code than necessary, sorry if it makes it more difficult. I was worried that I might accidentally delete something.
const int MAX=20;
//Struct Cell holds player and their symbol.
class Cell
{
private:
int Player;
char Symbol;
public:
Cell(void);
void setPlayer(int);
void setSymbol(char);
int getPlayer(void);
char getSymbol(void);
};
Cell::Cell(void)
{
Symbol ='-';
}
void Cell::setPlayer(int player_num)
{
Player = player_num;
}
void Cell::setSymbol(char rps)
{
Symbol = rps;
}
int Cell::getPlayer(void)
{
return Player;
}
char Cell::getSymbol(void)
{
return Symbol;
}
void Turn(int, int, Cell[MAX][MAX]);
void displayGrid(int, Cell[MAX][MAX]);
void main(void)
{
int size;
cout << "How big would you like the grid to be: ";
cin >> size;
//Checks to see valid grid size
while(size>MAX || size<3)
{
cout << "Grid size must between 20 and 3." << endl;
cout << "Please re-enter the grid size: ";
cin >> size;
}
int cnt=1;
int full;
Cell grid[MAX][MAX];
//I use full to detect when the game is over by squaring size.
full = size*size;
cout << "Starting a new game." << endl;
//Exits loop when cnt reaches full.
while(cnt<full+1)
{
displayGrid(size, grid); //calls function to display grid
if(cnt%2==0) //if cnt is even then it's 2nd players turn
cout << "Player 2's turn." << endl;
else
cout << "Player 1's turn" << endl;
Turn(size, cnt, grid); //calls Turn do each players turn
cnt++;
}
cout << endl;
cout << "Board is full... Game Over" << endl;
}
void displayGrid(int size, Cell grid[MAX][MAX])
{
cout << endl;
cout << " ";
for(int x=1; x<size+1; x++) // prints first row
cout << setw(3) << x; // of numbers.
cout << endl;
//Nested-For prints the grid.
for(int i=1; i<size+1; i++)
{
cout << setw(2) << i;
for(int c=1; c<size+1; c++)
{
cout << setw(3) << grid[i][c].getSymbol;
}
cout << endl;
}
cout << endl;
}
void Turn(int size, int cnt, Cell grid[MAX][MAX])
{
char temp;
char choice;
int row=0;
int column=0;
cout << "Enter the Row: ";
cin >> row;
cout << "Enter the Column: ";
cin >> column;
//puts what is in the current cell in "temp"
temp = grid[row][column].getSymbol;
//Checks to see if temp is occupied or not
while(temp!='-')
{
cout << "Cell space is Occupied..." << endl;
cout << "Enter the Row: ";
cin >> row;
cout << "Enter the Column: ";
cin >> column;
temp = grid[row][column].getSymbol; //exits loop when finally correct
}
if(cnt%2==0) //if cnt is even then its player 2's turn
{
cout << "Enter your Symbol R, P, or S (Capitals): ";
cin >> choice;
grid[row][column].setPlayer(1);
in >> choice;
}
//officially sets choice to grid cell
grid[row][column].setSymbol(choice);
}
else //if cnt is odd then its player 1's turn
{
cout << "Enter your Symbol r, p, or s (Lower-Case): ";
cin >> choice;
grid[row][column].setPlayer(2);
//checks for valid input by user1
while(choice!= 'r' && choice!='p' && choice!='s')
{
cout << "Invalid Symbol... Please Re-Enter: ";
cin >> choice;
}
//officially sets choice to grid cell.
grid[row][column].setSymbol(choice);
}
cout << endl;
}
Thanks alot for your help!
The following line:
cout << setw(3) << grid[i][c].getSymbol;
Doesn't call the function. Write this instead:
cout << setw(3) << grid[i][c].getSymbol();
Likewise for the other error messages.
The warning is generated because the erroneous line is the only time displayGrid uses the grid parameter.
You forgot the function parens:
cout << setw(3) << grid[i][c].getSymbol;
should be:
cout << setw(3) << grid[i][c].getSymbol();