My second last value is garbage,the program is about calculating sum - c++

#include <iostream>
using namespace std;
int main()
{
int oldsize;
string choice;
cout << "Welcome to the Walmart Calculation Center!";
cout << endl;
cout << "Enter the Number of Items" << endl;
cin >> oldsize;
int* items = new int[oldsize];
for (int i = 0; i < oldsize; i++)
{
cout << "ENTER THE PRICE OF ITEM" << i + 1 << "!" << endl;
cin >> items[i];
}
cout << "Do you want to add more items? (YES OR NO)" << endl;
cin >> choice;
if (choice == "YES")
{
int newbie;
int newsize;
int total = 0;
while (choice == "YES")
{
newsize = oldsize + 1;
int* Nitems = new int[newsize];
for (int i = 0; i < oldsize; i++)
{
Nitems[i] = items[i];
}
cout << "Enter the Price of New ITEM!" << endl;
cin >> newbie;
Nitems[oldsize] = newbie;
oldsize = newsize;
cout << "Do you want to add more items? (YES OR NO)" << endl;
cin >> choice;
if (choice=="NO")
{
for (int i = 0; i < newsize; i++)
{
cout << Nitems[i] << endl;
}
}
}
}
}
This program is about calculating sum of the bill at a store. and ask user that if he/she wants to enter any other item, until he/she says no. In the end it displays the total bill.

You never change items array, but you change oldsize variable which represents it's size. When you the try to copy items from items to Nitems, you go out of bounds of items array (because oldsize is bigger that actual size of array).
The simplest fix would be to repoint items to Nitems at the same moment when you change the size.
while (choice == "YES")
{
newsize = oldsize + 1;
int* Nitems = new int[newsize];
for (int i = 0; i < oldsize; i++)
{
Nitems[i] = items[i];
}
cout << "Enter the Price of New ITEM!" << endl;
cin >> newbie;
Nitems[oldsize] = newbie;
oldsize = newsize;
items = Nitems; //here
cout << "Do you want to add more items? (YES OR NO)" << endl;
cin >> choice;
if (choice=="NO")
{
for (int i = 0; i < newsize; i++)
{
cout << Nitems[i] << endl;
}
}
}
See the line marked with comment? It makes items pointer point to the same array as Nitems. There is no copying involved, if you change items[1], Nitems[1] would see the same change. But having two pointers to the same array let's you keep the current array when you create new array in the next iteration.
There is of course problem with memory leaks, but don't worry too much about that until you learn how to manage memory properly. Badly placed delete is much worse that memory leak (especially in such small programs).
And of course, your code would be much simpler if you used std::vector:
std::vector<int> items;
while (choice == "YES")
{
cout << "Enter the Price of New ITEM!" << endl;
cin >> newbie;
items.push_back(newbie);
cout << "Do you want to add more items? (YES OR NO)" << endl;
cin >> choice;
if (choice=="NO")
{
for (int i = 0; i < items.size(); i++)
{
cout << items[i] << endl;
}
}
}

I am unable to comment due to low reputation. But I feel you are still unclear about dynamic allocation concepts. You will need to delete if you create something using new to avoid memory leaks. This program can be much simpler like below. I still use new deliberately to show the delete scenario. Apart from that you also need to clear up some basics as given in comments. All the best!
#include <iostream>
using namespace std;
int main()
{
int oldsize, newbie;
int total=0;
string choice;
cout << "Welcome to the Walmart Calculation Center!";
cout << endl;
cout << "Enter the Number of Items" << endl;
cin >> oldsize;
int* items = new int[oldsize];
for (int i = 0; i < oldsize; i++)
{
cout << "ENTER THE PRICE OF ITEM" << i + 1 << "!" << endl;
cin >> items[i];
total+=items[i];
}
do {
cout << "Do you want to add more items? (YES OR NO)" << endl;
cin >> choice;
//if user inputs NO, break out of do while.
if(choice == "NO") break;
//continue here if YES
cout << "Enter the Price of New ITEM!" << endl;
cin >> newbie;
total+=newbie;
}while(choice=="YES");
cout << "Total: " << total << endl;
delete[] items;
}

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] << " ";
}
}

Program that checks whether numbers are already in an array

This program is supposed to accept values from the keyboard, and require that the user re-enter the value for the employee's id number. However it keeps outputting "Invalid variable" even if I enter a correct value. It needs to only output that if the value is already been entered. For example
if I enter "3453" as the id number it will still output "Invalid Variable" even if I have not entered that number before.
#include <iostream>
using namespace std;
struct Employee
{
int idNum;
double payRate;
char firstName, lastName;
};
int main()
{
int error;
const int SIZE = 5;
Employee employee[SIZE];
for (int k = 0; k < SIZE; ++k)
{
employee[k].idNum = 0;
employee[k].payRate = 0;
}
for (int count = 0; count < SIZE; ++count)
{
error = 0;
cout << "Enter the employee's id number " << endl;
cin >> employee[count].idNum;
for (int i = 0; i < SIZE; ++i)
{
if (employee[i].idNum == employee[count].idNum)
error = 1;
}
while (error == 1)
{
cout << "Invalid entry. Please enter a new id number " << endl;
cin >> employee[count].idNum;
for (int i = 0; i < SIZE; ++i)
{
error = 0;
if (employee[i].idNum == employee[count].idNum)
error = 1;
}
}
cout << "Enter the employee's pay rate " << endl;
cin >> employee[count].payRate;
cout << "Enter the employee's first name " << endl;
cin >> employee[count].firstName;
cout << "Enter the employee's last name " << endl;
cin >> employee[count].lastName;
int choice;
cout << "Enter 1 to search for an employee by id number, enter 2 to search by last name, and enter 3 to search by pay "
<< endl;
cin >> choice;
}
int choice;
cout << "Enter 1 to search for an employee by id number, enter 2 to search by last name, and enter 3 to search by pay "
<< endl;
cin >> choice;
if (choice == 1)
{
int idNumC;
cout << "Enter an id number ";
cin >> idNumC;
for (int count = 0; count < SIZE; ++count)
{
if (employee[count].idNum == idNumC)
cout << employee[count].idNum;
}
}
if (choice == 2)
{
char name;
cout << "Enter the employee's last name " << endl;
cin >> name;
for (int count = 0; count < SIZE; ++count)
{
if (employee[count].lastName == name)
cout << "ID number: " << employee[count].idNum
<< " First name: " << employee[count].firstName
<< " Last Name: " << employee[count].lastName
<< " Hourly Pay: " << endl;
}
}
if (choice == 3)
{
int name;
cout << "Enter the employee's last name " << endl;
cin >> name;
for (int count = 0; count < SIZE; ++count)
{
if (employee[count].payRate == name)
cout << "ID number: " << employee[count].idNum
<< " First name: " << employee[count].firstName
<< " Last Name: " << employee[count].lastName
<< " Hourly Pay: " << endl;
}
}
}
My program also will not accept a value of more than one letter into the name. If I try and enter that into the program, the program keeps printing "Invalid entry" until I hit ctrl+c.
for (int i = 0; i < SIZE; ++i)
This checks every element in the array, including the one you have just read. You probably meant to put
for (int i = 0; i < count; ++i)
which will check every element up to (but not including) the one you have just read.
in
for (int i = 0; i < SIZE; ++i)
{
if (employee[i].idNum == employee[count].idNum)
error = 1;
}
employee[count] is one of the employee[i] you're going to compare against which means at some point you will
if (employee[count].idNum == employee[count].idNum)
Which is guaranteed to be true.
But if instead you
int tempId;
cin >> tempId;
for (int i = 0; i < SIZE; ++i)
{
if (employee[i].idNum == tempId)
error = 1;
}
and then set
employee[count].idNum = tempId;
at some later time, you can avoid this problem.
Addendum: I recommend picking this logic up and placing it in its own function. That way A) you don't have to repeat it inside the loop a few lines down where you're repeating the check for each retry and it gets the logic out of the way of the rest of the code. B) you can use the same function later for any other "Does this employee exist?" checks you need to write in the future.
In general You want to have lots of simple, easily-tested functions over one monolithic jack-of-all-trades.

How create a user defined vector size with my existing code?

I have a program that takes in 10 "purchase prices" from a user and displays them in the console screen. I am attempting to modify the code to make it to where the user can determine how many inputs they like for "purchase prices" and then displays that amount of them on the console screen.
The current modification i was successful in was changing was the for loop inside the vector from for "(int i = 0; i < 10; i++)" to "for (int i = 0; i < purchases.size(); i++)" but from here I am stuck.
It seems that I may need some function or loop prior to the vector declaration to set the size variable based on user entries possibly but I am not sure. Thank you for you help-
My code:
vector<double> purchases(10);
{
for (int i = 0; i < purchases.size(); i++)
{
cout << "Enter a purchase amount: ";
cin >> purchases[i];
}
cout << "The purchase amounts are: " << endl;
for (int i = 0; i < 10; i++)
{
cout << purchases[i] << endl;
}
}
system("PAUSE");
return (0);
}
I can think of the following approaches.
Ask the user for the number of purchases they wish to enter. Then, create the vector with that size.
int num;
cout << "Enter the number of purchases: ";
cint >> num;
vector<double> purchases(num);
for (int i = 0; i < num; i++)
{
cout << "Enter a purchase amount: ";
cin >> purchases[i];
}
cout << "The purchase amounts are: " << endl;
for (int i = 0; i < num; i++)
{
cout << purchases[i] << endl;
}
When asking the user for the purchase price, provide the option to enter something else to stop. After each successful read, use push_back.
vector<double> purchases;
while ( true )
{
std::string s;
cout << "Enter a purchase amount or q to stop: ";
cin >> s;
if ( s == "q" )
{
break;
}
std::istringstream str(s);
double purchase;
str >> purchase;
purchases.push_back(purchase);
}
cout << "The purchase amounts are: " << endl;
size_t num = purchases.size();
for (int i = 0; i < num; i++)
{
cout << purchases[i] << endl;
}

Search in Dynamic Array

When I'm searching an integer in my dynamic array, the search function isn't working well as its always showing its positioned at 1. whether the data is actually there or not.
What i'm actually trying to do is using dynamic data structure, I'm adding the data. Deleting, searching and saving to txt file. and Loading it back. But the problem is search. I used switch cases and search is at Case 4.
#include<iostream>
#include<string>
#include<fstream> //to save file in text
using namespace std;
int main()
{
int *p1;
int size = 0;
int counter = 0;
p1 = new int[size];
int userchoice;
int i;
int position;
while (1)
{
cout << "Please enter your choice " << endl;
cout << endl;
cout << "To insert Press '1'" << endl;
cout << "To Delete press '2'" << endl;
cout << "To View press '3'" << endl;
cout << "To Search press '4'" << endl;
cout << "To Save Press '5'" << endl;
cout << "To Load Previously saved Data press '6'" << endl;
cout << "To Exit press '7'" << endl;
cout << endl;
cout << "Enter your choice: ";
cin >> userchoice;
switch (userchoice) // User's selection from the menu
{
case 1: //Insert Number
cout << "Enter a Number: ";
cin >> p1[size];
counter++;
size++; //Add's memory space
break;
case 2: //Delete Number
int udelete;
cout << "Enter a number to delete: ";
cin >> udelete; //User enters Number to be deleted
//Checking if the number is in an array.
for (position = 0; position<size; position++)
{
if (p1[position] == udelete)
break;
}
if (position>size)
{
cout << "The number is not in the memory: ";
cout << endl;
break;
}
for (i = position; i<size; i++) {
p1[i] = p1[i + 1];
}
size--;
cout << "Successfully Deleted!!! ";
cout << endl;
break;
case 3: // View
for (i = 0; i<size; i++)
{
cout << "Your data" << " " << i << " " << "-->" << p1[i] << endl;
}
break;
case 4:
{
int usearch;
cout << "Please enter the figure you would like to search ";
cout << "->";
cin >> usearch;
for (i = 0; i>size; i++)
{
if (p1[size] == usearch)
break;
}
if (usearch == size)
{
cout << "not found. ";
}
cout << "Position at: " << i + 1 << endl;
break;
}
case 5: // Save
{
ofstream save;
save.open("Dynamicdata.txt", ofstream::out | ofstream::app);
for (i = 0; i<size; i++)
{
save << p1[i] << endl;
}
save.close();
cout << "File Saved " << endl;
break;
}
case 6: //Read from File
{
string read;
ifstream file_("Dynamicdata.txt");
if (file_.is_open())
{
while (getline(file_, read))
{
cout << read << "\n";
}
file_.close();
}
else
cout << "File Not open" << endl;
cin.get();
break;
}
case 7:
{
return 0;
}
}
}
}
Your problem is that the size of your array is 0. Here you set size to 0 and then size for the size of p1
int size=0;
int counter=0;
p1 = new int[size];
You are going to need to make size bigger so that you can actually store elements in p1 or instead of using arrays and dynamic memory allocation use a std::vector and let it handle that for you.
The code has undefined behaviour because initailly the dynamically allocated array pointed to by pointer p1 has no elements
int size=0;
^^^^^^^^^^
//...
p1 = new int[size]; // size is equal to 0
So in the following code snippet an atttempt to write data to p1[size] results in undefined behaviour
case 1: //Insert Number
cout<<"Enter a Number: ";
cin>>p1[size]; // undefined behaviour
^^^^^^^^^^^^^
counter++;
size++; //Add's memory space
break;
You need to reallocate the array to reserve memory for the added new element.
Take into account that for example this loop
for (i = 0; i>size; i++)
^^^^^^^
{
if (p1[size] == usearch)
break;
}
will never iterate because variable i set to zero can not be greater than size that at least equal to zero.
And it would be logically more correct to write
if (p1[i] == usearch)
^^^^^
instead of
if (p1[size] == usearch)
^^^^^^^^
Consequently this if statement
if (usearch == size)
^^^^^^^
{
cout << "not found. ";
}
should be replaced with this for statement
if (i == size)
^^
{
cout << "not found. ";
}

C++ While loop and Array

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