This program uses inheritance and dynamic arrays
enum ItemType {BOOK, DVD, SOFTWARE, CREDIT};
class Sale
{
public:
Sale();
void MakeSale(ItemType x, double amt);
ItemType Item();
double Price();
double Tax();
double Total();
void Display();
private:
double price;
double tax;
double total;
ItemType item;
}
//****************************SALE.CPP*******************************
#include<iostream>
#include<cmath>
#include "sales.h"
using namespace std;
Sale::Sale()
{
price = 0;
tax = 0;
total = 0;
}
// Credit are suppose to have no tax all other purchases have
void Sale::MakeSale(ItemType x, double amt)
{
item = x;
if(item == CREDIT)
total = amt;
else
total = (amt * tax);
}
ItemType Sale::Item()
{
return item;
}
double Sale::Price()
{
return price;
}
double Sale::Tax()
{
return tax;
}
double Sale::Total()
{
return total;
}
// display function
void Sale::Display()
{
if(item = BOOK)
cout<<"BOOK"<<" "<<'$'<<price<<" ";
cout<<"Tax"<<" "<<'$'<<tax<<" "<<"Total:";
cout<<" "<<'$'<<total<<endl;
if(item = DVD)
cout<<"DVD"<<" "<<'$'<<price<<" ";
cout<<"Tax"<<" "<<'$'<<tax<<" "<<"Total:";
cout<<" "<<'$'<<total<<endl;
if(item = SOFTWARE)
cout<<"SOFTWARE"<<" "<<'$'<<price<<" ";
cout<<"Tax"<<" "<<'$'<<tax<<" "<<"Total:";
cout<<" "<<'$'<<total<<endl;
if(item = CREDIT)
cout<<"CREDIT" <<" "<<'$'<<price<<" ";
cout<<"Tax"<<" "<<'$'<<tax<<" "<<"Total:";
cout<<" "<<'$'<<total<<endl;
}
//****************************Register.h*******************************
#include<iostream>
#include "sales.h"
using namespace std;
const int BLOCKSIZE = 5;
class Register : Sales
{
public:
Register(int id, double start_amount);
~Register();
int GetID();
double GetAmount();
void RingUpSale(enum ItemType Saletype, double amount);
void ShowLast();
void ShowAll();
void Cancel();
double SalesTax(int n);
private:
int Register_ID;
int Current_ArraySize;
int Number_of_Records;
double Register_Amount
Sale *Sales_Array;
Sale *Temp_Array;
void expandlist();
void shrinklist();
}
//******************************Register.cpp*********************************
#include<iostream>
#include "register.h"
using namespace std;
// *******************************************************************
// * Initializing these values for a starting value
// *******************************************************************
int Current_ArraySize = 0;
int Number_of_Records = 0;
// ******************************************************************
// *
// * Function: Constructor for Register
// * Parameters: ID number and starting amount
// *
// * Description: Initializes the ID number and the register amount
// *
// ******************************************************************
Register::Register(int id, double amount)
{
int * Sales_Array;
Sales_Array = new int[BLOCKSIZE];
int Register_ID = id;
double Register_amount = amount;
}
// ******************************************************************
// *
// * Function: Destructor for Register
// * Parameters:
// *
// * Description: Deletes Sales Array
// *
// ******************************************************************
Register::~Register()
{
delete[] Sales_Array;
}
// ******************************************************************
// *
// * Function: GetID
// * Parameters:
// *
// * Description: returns ID
// *
// ******************************************************************
int Register::GetID()
{
return Register_ID;
}
// ******************************************************************
// *
// * Function: GetAmount
// * Parameters:
// *
// * Description: returns amount
// *
// ******************************************************************
double Register::GetAmount()
{
return Register_Amount;
}
// ******************************************************************
// *
// * Function: RingUpSale
// * Parameters: enum ItemType amd amount
// *
// * Description: Takes in items sold and amount then adds them
// * to the previous list.
// *
// ******************************************************************
Not sure why ringupsale is not working!
void Register::RingUpSale(enum ItemType Saletype, double amount)
{
Current_ArraySize++;
newSale_Array = new Sales_Array[Current_ArraySize];
//copy all the old sale items into the new list.
for (int i=0; i<Current_ArraySize; i++)
{
newSale_Array[i] = Sales_Array[i];
}
//add the new sale at the end of the new array
newSale_Array[Current_ArraySize-1] = newSale;
//set the sale array as the new array
Sales_Array = newSale_Array;
Number_of_Records++;
}
// ******************************************************************
// *
// * Function: ShowAll
// * Parameters:
// *
// * Description: Lists the contents of the register
// *
// ******************************************************************
I am trying to show all the contents of the sales array
void Register::ShowAll()
{
int i;
cout << "the elements int the array are:" <<endl;
// for(i=0; i<Current_ArraySize; i++)
// cout << Sales_Array(Sales_Array+i) << endl;
}
// ******************************************************************
// *
// * Function: ShowLast
// * Parameters:
// *
// * Description: Show the last transaction made
// *
// ******************************************************************
I am just trying to show the last content of the sales array
void Register::ShowLast()
{
cout << "The last sale was:" << endl;
// cout << Sale[Current_ArraySize - 1] << endl;
}
// ******************************************************************
// *
// * Function: Salestax
// * Parameters:
// *
// * Description: returns the amount of salestax
// *
// ******************************************************************
double Register::SalesTax(int n)
{
double RunTotal=0;
if (n<0)
{
cout<<"Invalid entry.";
return 0;
}
else if (n>Number_of_Records)
{
for(int i=0; i<=Number_of_Records; i++)
{
RunTotal=RunTotal+Sales_Array[i].Tax();
return RunTotal;
}
}
else
{
for(int i=0; i<=n; i++)
{
RunTotal=RunTotal+Sales_Array[i].Tax();
return RunTotal;
}
}
}
This is a problem:
Register::Register(int id, double amount)
{
int * Sales_Array;
Sales_Array = new int[BLOCKSIZE];
int Register_ID = id;
double Register_amount = amount;
}
as the local variable Sales_Array in the constructor of Register hides the member variable Register::Sales_Array, meaning Register::Sales_Array is an unintialised pointer. Register::Sales_Array is then used, causing undefined behaviour and will be the reason that Register::RingUpSale() is not working. Remove the declarations in the constructor and use an initializer list instead:
Register::Register(int id, double amount) :
Current_ArraySize(0),
Number_of_Records(0),
Sales_Array(0),
Register_ID(id),
Register_Amount(amount)
{}
Note that these lines introduced two new variables, unrelated to the class:
int Current_ArraySize = 0;
int Number_of_Records = 0;
Have also added these to the initializer list above.
Finally, you are violating the Rule of Three as you have dynamically allocated members but have not defined a copy constructor and assignment operator, or at least declared them private to make Register uncopyable.
As this is C++, use a std::vector<Sale> instead of explicitly managing dynamic memory.
Related
might be a stupid question and if it is, let me know, I will delete it as soon as possible. The thing is I have to make a deep copy in class "Kambarys" (ignore mixed languages, I know I shouldn't do that). Program terminates after trying to call function second time. Probably the problem is my syntax in constructor copy, but I can't find the correct one anywhere. One of the requirements is to create langas, durys and kambarys in dynamic memory using "new" and delete windows vector and door in Kambarys destructor. Appreciate the help!
Requirements:
In the main method, use the new operator to create room k1, add windows and doors to it. Write a constructor Room (const Room & k) that would create a correct copy. In the method main, write another room k2. Calculate the length of the baseboards / wall area.
Perform the following steps: k2 = * k1; delete k1;
#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;
class Langas{
private:
float height;
float widht;
static int countL;
public:
Langas(float h, float w){
this->height=h;
this->widht=w;
countL++;
}
~Langas(){
--countL;
}
float getHeight(){
return height;
}
float getWidht(){
return widht;
}
static int getWindowCount(){
return countL;
}
};
class Durys{
private:
float heightD;
float widhtD;
static int countD;
public:
Durys(float hD, float wD){
this->heightD=hD;
this->widhtD=wD;
countD++;
}
~Durys(){
--countD;
}
float getHeightD(){
return heightD;
}
float getWidhtD(){
return widhtD;
}
static int getDoorCount(){
return countD;
}
};
class Kambarys{
private:
float heightK;
float widhtK;
float lenghtK;
public:
vector<Langas*> windows;
Durys* door;
Kambarys(float hK, float wK, float lK){
this->heightK=hK;
this->widhtK=wK;
this->lenghtK=lK;
}
Kambarys(const Kambarys &k){
this->door=k.door;
this->windows=k.windows;
heightK=k.heightK;
widhtK=k.widhtK;
lenghtK=k.lenghtK;
}
~Kambarys(){
door=NULL;
for(int i=0; i<windows.size(); i++){
delete windows[i];
}
windows.clear();
delete door;
}
float getHeightK(){
return heightK;
}
float getWidhtK(){
return widhtK;
}
float getLenghtK(){
return lenghtK;
}
void addWindow(Langas* w){
windows.push_back(w);
}
void addDoor(Durys *d){
door=d;
}
};
float countWallPlot(Kambarys* k){
float cWPlot=(2*k->getLenghtK()*k->getHeightK())+(2*k->getWidhtK()*k->getHeightK());
for(int i=0; i<k->windows.size(); i++){
cWPlot-=((k->windows[i]->getHeight()))*(k->windows[i]->getWidht());
}
cWPlot-=((k->door->getHeightD()))*(k->door->getWidhtD());
return cWPlot;
}
float countLenght(Kambarys* k){
float floorL=(k->getLenghtK()*k->getWidhtK()*2);
floorL-=(k->door->getWidhtD());
return floorL;
}
int Langas::countL=0;
int Durys::countD=0;
int main(){
Langas *langas1=new Langas(3.4, 1.2);
Durys *durys=new Durys(3.1, 1.5);
Langas *langas2=new Langas(6.4, 1.5);
Kambarys *k=new Kambarys(30.4, 40.1, 50.1);
Kambarys *k2=k;
k->addWindow(langas1);
k->addWindow(langas2);
k->addDoor(durys);
cout<<countWallPlot(k)<<" "<<countLenght(k)<<endl;
cout<<"Window count "<<Langas::getWindowCount()<<", door count "<<Durys::getDoorCount()<<endl;
k2=k;
delete k;
cout<<countWallPlot(k2)<<" "<<countLenght(k2)<<endl;
cout<<"Window count "<<Langas::getWindowCount()<<", door count "<<Durys::getDoorCount()<<endl;
}
You have to allocate memory for k2 and copy the object, not the pointer.
You have to allocate memory in the copy constructor and copy assignment operator.
door=NULL; before delete door; would skip the delete and cause a memory leak.
windows.clear(); is not necessary in the destructor. Keep your code simple.
EDIT: After you added "Perform the following steps: k2 = * k1; delete k1;" I made k2 an object, not a pointer.
#include <iostream>
#include <vector>
class Langas {
private:
float height;
float width;
static int count;
public:
Langas(float h, float w): height(h), width(w) {
++count;
}
~Langas() { --count; }
float getHeight() const { return height; }
float getWidht() const { return width; }
static int getWindowCount() { return count; }
};
class Durys {
private:
float height;
float width;
static int count;
public:
Durys(float h, float w): height(h), width(w) {
++count;
}
~Durys() { --count; }
float getHeight() const { return height; }
float getWidth() const { return width; }
static int getDoorCount() { return count; }
};
class Kambarys {
private:
float height;
float width;
float length;
public:
std::vector<Langas *> windows;
Durys *door = nullptr;
Kambarys(float hK, float wK, float lK): height(hK), width(wK), length(lK) {}
Kambarys(const Kambarys &k): height(k.height), width(k.width), length(k.length), windows(), door(k.door ? new Durys(k.door->getHeight(), k.door->getWidth()) : nullptr) {
for (const auto window : k.windows) {
windows.emplace_back(new Langas(window->getHeight(), window->getWidht()));
}
}
Kambarys &operator=(const Kambarys &k) {
door = k.door ? new Durys(k.door->getHeight(), k.door->getWidth()) : nullptr;
for (const auto window : k.windows) {
windows.emplace_back(new Langas(window->getHeight(), window->getWidht()));
}
height = k.height;
width = k.width;
length = k.length;
return *this;
}
~Kambarys() {
for (auto window : windows) {
delete window;
}
delete door;
}
float getHeight() const { return height; }
float getWidth() const { return width; }
float getLength() const { return length; }
void addWindow(Langas *w) { windows.emplace_back(w); }
void addDoor(Durys *d) { door = d; }
};
float countWallPlot(const Kambarys &k) {
float cWPlot = 2 * k.getLength() * k.getHeight() + 2 * k.getWidth() * k.getHeight();
for (const auto window : k.windows) {
cWPlot -= window->getHeight() * window->getWidht();
}
cWPlot -= k.door->getHeight() * k.door->getWidth();
return cWPlot;
}
float countLength(const Kambarys &k) {
float floor = k.getLength() * k.getWidth() * 2;
floor -= k.door->getWidth();
return floor;
}
int Langas::count = 0;
int Durys::count = 0;
int main() {
Langas *langas1 = new Langas(3.4, 1.2);
Durys *durys = new Durys(3.1, 1.5);
Langas *langas2 = new Langas(6.4, 1.5);
Kambarys *k = new Kambarys(30.4, 40.1, 50.1);
Kambarys k2(*k);
k->addWindow(langas1);
k->addWindow(langas2);
k->addDoor(durys);
std::cout << countWallPlot(*k) << " " << countLength(*k) << std::endl;
k2 = *k;
std::cout << "Window count " << Langas::getWindowCount() << ", door count " << Durys::getDoorCount() << std::endl;
delete k;
std::cout << countWallPlot(k2) << " " << countLength(k2) << std::endl;
std::cout << "Window count " << Langas::getWindowCount() << ", door count " << Durys::getDoorCount() << std::endl;
}
I have a class Dog and a class Owner. In class Dog there is a member which is a reference to a specimen of class Owner (breeder). So i need this specimen to be created when i have at least 1 Dog specimen and to be shared and used in their constructors by other Dog examplars.
class Dog
{
private:
Owner & m_owner;
...
public:
static Owner & m_breeder;
...
}
class Owner
{private:
...
public:
...
}
dog.cpp
{
#include "dog_class.h"
#include <iostream>
#include <cstdlib>
#include <string>
#include <ctime>
Owner breeder("breeder");
Owner & Dog::m_breeder=breeder;
//methods here
Dog () : m_owner(m_breeder) {}
...
}
This doesn't work (error:use of deleted function 'Dog & Dog::operator=(const Dog&);
I tried to include Owner as "static Owner breeder;" in public section of class Dog and later initialize it inside dog.cpp but it doesn't work either.
What's wrong and how my goal can be obtained?
Here some more code, basically, constructors of class Dog and Owner:
dog_class_methods.cpp
Dog::Dog(std::string name, int size, int status, int loyalty, int sex, int price, std::vector<Dog> * market, Owner & owner) : m_owner(owner)
{
m_name=name;
m_size=size;
m_status=status;
m_loyalty=loyalty;
m_sex=sex;
m_price=price;
m_market=market; //pointer to the market
m_market->push_back(*this);
//break_out();
}
Dog::Dog() : m_owner(m_breeder)
{
m_name="Fang";
srand(time(NULL));
m_size=(rand()%10)+1; //small: random number from 1 to 10;
m_status=0; //not owned
m_loyalty=(rand()%10)+1; //from 1 to 10
Owner no_one("no_one");
//m_owner=no_one;
m_sex=rand()%2; //rand 0 or 1;
m_price=rand()%1001; //0 - 1000;
//show_data();
//break_out();
}
owner_class_methods.cpp
Owner::Owner()
{
m_name="random";
m_goodness=(rand()%10+1);
m_size=(rand()%10+1);
m_money=rand()%1001;
m_agility=(rand()%10+1);
m_int=(rand()%10+1);
//std::cout<<"Hi! I am the "<<m_name<<std::endl;
}
Owner::Owner(std::string name)
{
if (name=="no one")
{
m_name="no one";
m_goodness=0;
m_size=0;
m_money=0;
m_agility=0;
m_int=0;
std::cout<<"Hi! I am the "<<m_name<<std::endl;
}
else
{
m_name=name;
m_goodness=(rand()%10+1);
m_size=(rand()%10+1);
m_money=rand()%1001;
m_agility=(rand()%10+1);
m_int=(rand()%10+1);
std::cout<<"The '"<<m_name<<"' owner made"<<std::endl;
}
}
Owner::Owner(std::string name, int goodness, int size, int money, int agility, std::vector<Dog> doglist)
{
m_name=name;
m_size=size;
m_money=money;
m_agility=agility;
for (int i=0; i<doglist.size();i++)
m_doglist.push_back(doglist[i]);
}
"use of deleted function 'Dog& Dog::operator=(const Dog&)" keeps arising!! Please, help!
class Dog {
Dog(Owner& owner)
: m_owner(owner)
{}
Owner& m_owner;
};
Owner breeder("breeder");
Dog the_dog(breeder);
The error appeared because there was a use of vector which required for Dog objects to be copyable, but there was a reference member in class and operator= needed to be written:
Dog Dog::operator=(const Dog & a)
{ m_owner=a.m_owner;
m_loyalty=a.m_loyalty;
m_size=a.m_size;
m_status=a.m_status;
m_sex=a.m_sex;
m_price=a.m_price;
m_market=a.m_market; //market один для всех собак;
m_name=a.m_name;
return *this;
}
This solved the whole thing.
package services;
import java.util.Scanner;
/**
* This class contain the main method for testing
* the Service class and the methods for getting user input.
*/
public class Pr6 {
/**
* A Scanner is used to get user input.
*/
private static Scanner scanner = new Scanner(System.in);
/**
* This method runs the program.
* #param args none expected.
*/
public static void main(String[] args) {
boolean quit = false;
do {
int choice = getUserChoiceFunction();
switch (choice) {
case 1:
System.out.println("\n==== Testing countVowels ====");
String s = getVowelsString();
int count = Services.countVowels(s);
System.out.println("\nThere are " + count + " vowels in this string!");
break;
case 2:
System.out.println("\n==== Testing fill ====");
int n = getArraySize();
int a = getA();
int b = getB(a);
int[] array = Services.fill(n, a, b);
System.out.print("\nResult array: ");
print(array);
break;
case 3:
quit = true;
break;
}
} while (!quit);
}
/**
* This method prints a given array.
* #param array the array to print.
*/
private static void print(int[] array) {
System.out.print("[");
for (int i = 0; i < array.length; i++) {
System.out.print(array[i]);
if (i < array.length - 1) {
System.out.print(", ");
}
}
System.out.println("]");
}
/**
* This method gets the upper bound b.
*
* It must be greater than lower bound a.
*
* #param a lower bound.
* #return upper bound.
*/
private static int getB(int a) {
do {
System.out.print("\nEnter b: ");
int b = scanner.nextInt();
scanner.nextLine();
if (a < b) {
return b;
}
System.out.println("Error! a should be less than b!");
} while (true);
}
/**
* This method gets the lower bound a.
* #return the lower bound.
*/
private static int getA() {
System.out.print("\nEnter a: ");
int a = scanner.nextInt();
scanner.nextLine();
return a;
}
/**
* This method gets the size of the array.
*
* It should be greater than zero.
*
* #return the size of the array.
*/
private static int getArraySize() {
do {
System.out.print("\nEnter n: ");
int n = scanner.nextInt();
scanner.nextLine();
if (n <= 0) {
System.out.println("Error! n must be greater than 0!");
}
else {
return n;
}
} while (true);
}
/**
* This method gets the string to count vowels in.
* #return the string provided by the user.
*/
private static String getVowelsString() {
System.out.print("\nEnter string: ");
String input = scanner.nextLine();
return input;
}
/**
* This method allows a user to pick a choice
* from a given menu.
* #return the user choice.
*/
public static int getUserChoiceFunction() {
do {
System.out.println("\n1. countVowels" +
"\n2. fill" +
"\n3. Quit");
System.out.print("\nYour choice: ");
int choice = scanner.nextInt();
scanner.nextLine();
if (choice >= 1 && choice <= 3) {
return choice;
}
System.out.println("\nError! Wrong choice!");
} while (true);
}
}
package services;
import java.util.Random;
/**
* This class contains countVowels and fill methods.
*/
public class Services {
/**
* This method counts and returns the number of vowels
* in a given string.
*
* Vowels are letters: A, E, I, O, U.
*
* The count is case-insensitive.
*
* #param s the string.
* #return the number of vowels in the string.
*/
public static int countVowels(String s) {
char[] vowels = {'a', 'e', 'i', 'o', 'u'};
int count = 0;
for (char letter: s.toCharArray()) {
for (char vowel: vowels) {
if (Character.toLowerCase(letter) == vowel) {
count++;
}
}
}
return count;
}
/**
* This method creates and fills an array of size n
* with random number in the range [a; b].
*
* #param n the size of the array.
* #param a the lower bound of the random numbers.
* #param b the upper bound of the random numbers.
* #return the array of size n filled with random
* numbers in range [a; b].
*/
public static int[] fill(int n, int a, int b) {
int[] array = new int[n];
for (int i = 0; i < array.length; i++) {
array[i] = generateRandomNumber(a, b + 1);
}
return array;
}
/**
* Generates a random number in a given range.
*
* #param min inclusive lower bound.
* #param max exclusive upper bound.
* #return the random number in range [min; max).
*/
private static int generateRandomNumber(int min, int max) {
Random random = new Random();
return random.nextInt(max - min) + min;
}
}
I need to write the name, act# balance and address of the object that is stored in the vector, to a file.
I believe I have the program to push the objects into the vectors, but since they are vectors of object pointers I am having problems figure out how to call the object and print all 3 objects out.
Main.cpp
vector<Account*> accounts;
accounts.push_back(new Savings(new Person("Bilbo Baggins", "43 Bag End"), 1, 500, 0.075));
accounts.push_back(new Checking(new Person("Wizard Gandalf", "Crystal Palace"), 2, 1000.00, 2.00));
accounts.push_back(new Savings(new Person("Elf Elrond", "Rivendell"), 3, 1200, 0.050));
ofstream outFile;
outFile.open("accounts.txt");
if (outFile.fail())
{
cout << "\nYour file did not open, the program will now close!\n";
system("PAUSE");
return 0;
}
else
{
cout << "\nBINGO!!! It worked.\n\n";
system("PAUSE");
cout << "\n";
}
// New : Using a loop, send messages to each of the three Account objects to write themselves out to the file.
cout << "\nNow we are going to write the information to \"Accounts.txt\" \n\n";
system("PAUSE");
for (int i = 0; i < accounts.size(); i++) {
accounts[i]->writeAccount(outFile);
}
Account.h
#pragma once
#include <string>
#include <iostream>
#include "Person.h"
using namespace std;
// Account class - abstract/parent class
class Account
{
private:
int actNumber;
double actBallance;
Person PersonName;
public:
Account();
Account(int, double, Person*);
int getActNumber();
virtual double getActBallance();
string getName();
string getAdd();
void deposit(double);
void withdrawl(double);
virtual void writeAccount(ofstream&);
virtual void readAccount(ifstream&);
void testAccount(int i);
};
// Checking class: inherits from the Account class
class Checking : public Account
{
private:
double monthlyFee;
public:
Checking();
Checking(Person*, int, double, double);
void setMonthlyFee(double);
double getActBallance();
void writeAccount(ofstream&);
void readAccount(ifstream&);
};
// Savings class: inherits from the Account class
class Savings : public Account
{
private:
int interestRate;
public:
Savings();
Savings(Person*, int, double, double); // person, act#, Ballance, Interest Rate
void setInterestRate(double);
double getActBallance();
void writeAccount(ofstream&);
void readAccount(ifstream&);
};
Account.cpp
#include "Account.h"
#include <string>
using namespace std;
Account::Account()
{
actNumber = 0;
actBallance = 0.0;
}
Account::Account(int act, double bal, Person* name)
{
actNumber = act;
actBallance = bal;
}
int Account::getActNumber()
{
return actNumber;
}
double Account::getActBallance()
{
return actBallance;
}
string Account::getName()
{
return PersonName.getName();
}
string Account::getAdd()
{
return PersonName.getAddress();
}
void Account::deposit(double money)
{
actBallance += money;
}
void Account::withdrawl(double money)
{
actBallance -= money;
}
void Account::writeAccount(ofstream& output)
{
output << actNumber << "\n" << actBallance << "\n" << PersonName.getName() << "\n" << PersonName.getAddress() << endl;
}
void Account::readAccount(ifstream& output)
{
output >> actNumber;
output >> actBallance;
}
// Checking Account
Checking::Checking() {
monthlyFee = 0;
}
Checking::Checking(Person* per, int actNum, double bal, double interest) {
bal -= monthlyFee;
Account:Account(actNum, bal, per);
}
void Checking::setMonthlyFee(double fee) {
monthlyFee = fee;
}
double Checking::getActBallance() {
double ballance = Account::getActBallance();
return ballance = monthlyFee;
}
void Checking::readAccount(ifstream& output) {
int actNumber = Account::getActNumber();
int actBallance = Account::getActBallance() - monthlyFee;
output >> actNumber;
output >> actBallance;
}
void Checking::writeAccount(ofstream& output) {
int actNumber = Account::getActNumber();
int actBallance = Account::getActBallance();
output << actNumber << "\n" << actBallance << endl;
}
// Savings Account
Savings::Savings() {
interestRate = 0;
}
// Savings(Person, int, double, double) // person, act#, Ballance, Interest Rate
Savings::Savings(Person* per, int actNum, double bal, double interest) {
bal += (bal * interest);
Account:Account(actNum, bal, per);
}
void Savings::setInterestRate(double rate) {
interestRate = rate;
}
double Savings::getActBallance() {
double ballance = Account::getActBallance();
return ballance + (ballance * interestRate);
}
void Savings::readAccount(ifstream& output) {
double actBallance = Account::getActBallance();
int actNumber = Account::getActNumber();
actBallance += (actBallance * interestRate);
output >> actNumber;
output >> actBallance;
}
void Savings::writeAccount(ofstream& output) {
int actNumber = Account::getActNumber();
int actBallance = Account::getActBallance();
output << actNumber << "\n" << actBallance << endl;
}
I realize I am so far off... but I have been at this for HOURS and I can not figure out for the life of me, but to take the vector of object pointers and output the objects values.
Person.h
#pragma once
#include <string>
#include <fstream>
using namespace std;
class Person
{
private:
string name;
string address;
public:
Person();
Person(string a, string b);
string getName();
string getAddress();
void writePerson(ofstream&);
void readPerson(ifstream&);
};
Person.cpp
#include "Person.h"
#include <string>
using namespace std;
Person::Person()
{
name = "NAME";
address = "123 STREET";
}
Person::Person(string a, string b)
{
name = a;
address = b;
}
string Person::getName()
{
return name;
}
string Person::getAddress()
{
return address;
}
void Person::writePerson(ofstream& output)
{
output << name << " " << address << endl;
}
void Person::readPerson(ifstream& output)
{
output >> name;
output >> address;
Person(name, address);
}
Read again your course books on constructors: there are severe issues in all of your constructors. As a result, you don't initialize the object member variables, and you effectively end up printing lots of zeros and empty strings...
Firstly, for your base-class, you must initialize the person name. You should have written:
Account::Account(int act, double bal, Person* name)
: actNumber(act)
, actBallance(bal)
, PersonName(name)
{}
Secondly, for your derived classes, the initialisation of the base-class must be done in the initializer-list, not in the body of the ctor. Here is for exemple the correct definition for the Checking's ctor:
Checking::Checking(Person* per, int actNum, double bal, double interest)
: Account(actNum, bal, per)
, monthlyFee(-bal)
{}
Thirdly, be careful to initialize the member variables with the arguments of the ctor. You sometimes do the opposite and assign the ctor arguments with the (uninitialized) member variables.
BTW, Account is a base-class for a polymorphic hierarchy: thus, the Account destructor must be declared virtual.
A problem has come up in my application where my PrintAll function will not work correctly and only ultimately crash my application. My app is supposed to read strings from a file and insert them into an array. The problem is it is reading incorrectly and will ultimately crash my app. Here is where I think the problem lies:
int main()
{
LoadMovies();
MovieList *movies = LoadMovies();
//movies->MovieList::PrintAll();
// // test methods for the Movie and MovieList classes
//PrintAllMoviesMadeInYear(movies, 1984);
//PrintAllMoviesWithStartLetter(movies, 'B');
//PrintAllTopNMovies(movies, 5);
//delete movies;
return 0;
}
MovieList* LoadMovies()
{
vector<string> movies;
ReadMovieFile(movies);
MovieList ml = MovieList(movies.size());
string name;
int year;
double rating;
int votes;
for (int i = 0; i < movies.size(); i++)
{
istringstream input_string(movies[i]);
getline(input_string, name, '\t');
input_string >> year >> rating >> votes;
Movie movie (name, year, votes, rating);
ml.Add(movie);
}
ml.PrintAll();
}
Complete Example:
/*
* File: MovieStatsProgram.cpp
* Author:
* Date:
* ===============================================================
* This is a console app to test the Movie and MovieList classes.
*
* TODO:
*
* You need to finish the implementation of the loadMovies method
* to create and initialize the MovieList object.
*
* You also need to create three static methods:
*
* PrintAllMoviesMadeInYear - it will print all the movies made in a
* given year once sort in alphabetical order and once sorted by the number
* of votes with the movie with the most number of votes printed first.
*
* PrintAllMoviesWithStartLetter - it will print all the movies started with
* a given letter sorted in alphabetical order
*
* PrintAllTopNMovies - it will display the top N movies based on the number of
* votes
*/
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <iomanip>
#include <fstream>
using namespace std;
class Movie {
public:
Movie();
Movie(string n, int y, int v, double r);
string get_name();
void set_name(string n);
int get_year();
void set_year(int y);
int get_votes();
void set_votes(int v);
double get_rating();
void set_rating(double r);
string PrintMovie();
private:
string name;
int year_made;
int votes;
double rating;
};
Movie::Movie() {
name = "null";
year_made = 0;
votes = 0;
rating = 0.0;
}
Movie::Movie(string n, int y, int v, double r) {
name = n;
year_made = y;
votes = v;
rating = r;
}
string Movie::get_name() {
return name;
}
void Movie::set_name(string n) {
name = n;
}
int Movie::get_year() {
return year_made;
}
void Movie::set_year(int y) {
year_made = y;
}
int Movie::get_votes() {
return votes;
}
void Movie::set_votes(int v) {
votes = v;
}
double Movie::get_rating() {
return rating;
}
void Movie::set_rating(double r) {
rating = r;
}
string Movie::PrintMovie() {
cout << fixed << setprecision(1) << rating << "\t\t" << votes << "\t\t" << "(" <<
year_made << ")" << "\t" << name << endl;
}
class MovieList {
public:
MovieList(int size);
~MovieList();
int Length();
bool IsFull();
void Add(Movie const& m);
string PrintAll();
private:
Movie* movies;
int last_movie_index;
int movies_size;
int movie_count = 0;
};
MovieList::MovieList(int size) {
movies_size = size;
movies = new Movie[movies_size];
last_movie_index = -1;
}
MovieList::~MovieList() {
delete [] movies;
}
int MovieList::Length() {
return last_movie_index;
}
bool MovieList::IsFull() {
return last_movie_index == movies_size;
}
void MovieList::Add(Movie const& m)
{
if (IsFull()) {
cout << "Cannot add movie, list is full" << endl;
return;
}
++last_movie_index;
movies[last_movie_index] = m;
}
string MovieList::PrintAll() {
for (int i = 0; i < last_movie_index; i++) {
movies[last_movie_index].Movie::PrintMovie();
//cout << movies[last_movie_index] << endl;
}
}
void ReadMovieFile(vector<string> &movies);
MovieList* LoadMovies();
enum MovieSortOrder
{
BY_YEAR = 0,
BY_NAME = 1,
BY_VOTES = 2
};
int main()
{
LoadMovies();
MovieList *movies = LoadMovies();
//movies->MovieList::PrintAll();
// // test methods for the Movie and MovieList classes
//PrintAllMoviesMadeInYear(movies, 1984);
//PrintAllMoviesWithStartLetter(movies, 'B');
//PrintAllTopNMovies(movies, 5);
//delete movies;
return 0;
}
MovieList* LoadMovies()
{
vector<string> movies;
ReadMovieFile(movies);
MovieList ml = MovieList(movies.size());
string name;
int year;
double rating;
int votes;
for (int i = 0; i < movies.size(); i++)
{
istringstream input_string(movies[i]);
getline(input_string, name, '\t');
input_string >> year >> rating >> votes;
Movie movie (name, year, votes, rating);
ml.Add(movie);
}
ml.PrintAll();
}
void ReadMovieFile(vector<string> &movies)
{
ifstream instream;
instream.open("imdbtop250.txt");
if (instream.fail())
{
cout << "Error opening imdbtop250.txt" << endl;
exit(1);
}
while (!instream.eof())
{
string movie;
getline(instream, movie);
movies.push_back(movie);
}
instream.close();
}
When I use MovieList::PrintAll in the main function, my function just crashes, and when I put it in the LoadMovies function, it will read and add data incorrectly before crashing. The size of the list is 251 and the application will just read the same data 251 times.
You have a two part problem:
1: As Brad S stated, your function returns nothing. This is a no-no.
MovieList* LoadMovies()
{
MovieList ml = MovieList(movies.size());
// Your function returns a pointer to a MovieList, so...
return &ml;
}
So, problem #2 is that you're going to return a pointer to something you created on the stack in your function. When you try to access it outside of your function, you'll run into undefined behavior.
Option 1:
MovieList* ml = new MovieList( movies.size() );
return ml;
You now need to delete ml when you're done w/ it.
Option 2:
Change your function to return a non-pointer... then you don't have the hassle of managing the memory.
EDIT: Try this
int main()
{
// Don't need this
// LoadMovies();
MovieList *movies = LoadMovies();
// Uncommented this
delete movies;
return 0;
}
MovieList* LoadMovies()
{
vector<string> movies;
ReadMovieFile(movies);
// CHANGE
MovieList* ml = new MovieList(movies.size());
// CHANGE
string name;
int year;
double rating;
int votes;
for (int i = 0; i < movies.size(); i++)
{
istringstream input_string(movies[i]);
getline(input_string, name, '\t');
input_string >> year >> rating >> votes;
Movie movie (name, year, votes, rating);
ml.Add(movie);
}
ml.PrintAll();
// CHANGE
return ml;
}
Your MovieList class has a fundamental problem. This comes to light on this line:
MovieList ml = MovieList(movies.size());
Your MovieList class has a member that is a pointer to dynamically allocated memory. Once you have this, you have to manage copying and assignment by creating a user-defined copy constructor and assignment operator.
The easiest fix for this is to use std::vector<Movie> instead of Movie * as a member variable of MovieList. Then copy-assignment comes for free and you don't need to implement further functions.
However, if you can't use std::vector for some reason, the following functions can be added:
class MovieList {
public:
//...
MovieList(const MovieList& m);
MovieList& operator=(MovieList m);
//...
};
#include <algorithm>
//...
// copy constructor
MovieList::MovieList(const MoveList& m) {
movies_size = m.size;
movie_count = m.movie.count;
last_movie_index = m.last_movie_index;
movies = new Movie[movies_size];
for (int i = 0; i < movies_size; ++i)
movies[i] = m.movies[i];
}
//...
// assignment operator
MovieList& MovieList::operator=(MoveList m) {
std::swap(m.movie_size, movie_size);
std::swap(m.last_movie_index, last_movie_index);
std::swap(m.movies, movies);
std::swap(m.movie_count, moviE_count);
return *this;
}
The easiest way to describe this to you is not to describe what these do. The best thing for you is to use your debugger and put a breakpoint in any of these functions and step through the code. When you hit the line I mentioned above, you will more than likely see that the copy constructor function is called -- then you can see it in action as to what it is doing.
The assignment operator is the function that's called when you assign an existing MovieList to another MovieList. It's implemented via the copy/swap idiom. This relies on a working copy constructor (provided above), and a destructor (which you already provided in your code). It works by creating a temporary MovieList, and swapping out the internals of the current MovieList with the temporary MovieList. There are many threads on SO as to how this works.
As to the reason why you need these functions above is that without the above functions, the line:
MovieList ml = MovieList(movies.size());
will create two MovieList objects, one temporary and one non-temporary, however the movies pointer for both will be pointing to the same memory. When the temporary is destroyed, the destructor is called, thus deleting the memory pointed to by movies. Now you have m1 pointing to memory that has gone up in smoke. Bad news when you try to use m1.
The user-defined copy and assignment functions above properly copy the object so that you get two distinct memory allocations for movies, so that when the destructor is called, the memory deleted will be unique to that object.
Again, all of this would be alleviated if you used std::vector and forego having to write copy ctor/assignment operators.
I see this error when running the below code:
Segmentation fault (core dumped)
I can't find the reason.
#ifndef DQMCBASE__H
#define DQMCBASE__H
const double pi=3.141592645;
#define rnd() ((double)rand())/ RAND_MAX
/**
* The basic walker class. This class serves the purpose of providing
* a structure that can be reused by inheriting.
*/
class DQMCWalker {
double _x; ///< dummy variable to implement basic 1D Harmonioscillator example.
This variable will be removed in future versions.
double _timeStep; ///< is the timestep in between to simultanious simulations
public:
DQMCWalker();
~DQMCWalker();
/**
* implements a normal distribution that can be used for the walking
* process defined in
* #see WalkNormal()
*
* #param variance the variance of the distribution.
* #param meanvalue the mean value of the distribution.
*
* #return A double distributed according to a normal distribution.
*/
double NormalDistribution(double variance, double meanvalue);
/**
* a virtual function that describes the walking process of the walker.
*
* #return returns 0, always.
*/
virtual int WalkNormal();
virtual double Potential();
virtual double Weight(double);
int Copy(DQMCWalker);
double SetDeltaT(double);
double GetDeltaT();
};
/* *
* The simulation class is a basic class that implements the basic features of walking, branching
* TODO
*/
template <class walker>
class DQMCSimulation {
walker* _walkers;
walker* _copies;
double _refE;
double _timeStep;
int _population;
int _max_walkers;
int _last_pop,_cur_pop,_nCopies;
public:
/**
* The constructor is used to define the simulation parameters of an instance. It takes two parameters,
* namely, the number of walkers and the time step in between two iterations.
*
* #param n the number of walkers used in the simulation.
* #param dt the time step in between two iterations.
*/
DQMCSimulation(int n, double dt);
~DQMCSimulation();
/**
* This function is used to perform one iteration. Every time this function is called
* a walkers are move according to the implementation of DQMCWalker::Walk(), next the
* reference energy is calculted according to the formula
* TODO
* and lastly, a birth-death process is performed.
*/
int Iterate();
double GetReferenceEnergy();
walker* WalkerArray();
};
#endif
up to here can be embeded into DQMCBase.h file
/* DQMCBase.cpp */
#include <iostream>
#include<math.h>
#include<stdlib.h>
#include<ctime>
//#include <DQMCBase.h>
using namespace std;
DQMCWalker::DQMCWalker() {
_timeStep=0.1;
_x=0.0;
}
DQMCWalker::~DQMCWalker() {
_x=0.0;
}
double DQMCWalker::NormalDistribution(double variance=1.0, double meanvalue=0.0) {
int samples=12;
double res = 0.0;
for(int i=0;i<samples;i++)
res +=rnd();
res = (res - samples*0.5)*sqrt(variance)+meanvalue;
return res;
}
int DQMCWalker::WalkNormal() {
_x+=NormalDistribution(1.0,0.0)*sqrt(_timeStep);
return 0;
}
double DQMCWalker::Potential() {
return 0.5*_x*_x;
}
double DQMCWalker::Weight(double refE) {
return exp(-(Potential()-refE)*_timeStep);
}
int DQMCWalker::Copy(DQMCWalker w) {
_x = w._x;
return 0;
}
double DQMCWalker::SetDeltaT(double timeStep) {
return (_timeStep = timeStep);
}
double DQMCWalker::GetDeltaT() {
return _timeStep;
}
template <class walker>
DQMCSimulation<walker>::DQMCSimulation(int n, double dt) {
_max_walkers = n;
_timeStep = dt;
_population = n;
_last_pop = _cur_pop = _population;
_walkers = new walker[2*n];
_copies = new walker[2*n];
for(int i=0;i<2*n; i++) {
_walkers[i].SetDeltaT(dt);
_copies[i].SetDeltaT(dt);
}
}
template<class walker>
DQMCSimulation<walker>::~DQMCSimulation() {
delete[] _walkers;
}
template <class walker>
int DQMCSimulation <walker>::Iterate() {
int i;
/* Make the walkers walk */
for(i=0;i<_cur_pop;i++)
_walkers[i].WalkNormal();
/* Calculating the reference energy */
double avg=0.0;
for(i=0;i<_cur_pop;i++)
avg += _walkers[i].Potential();
avg/=_cur_pop;
_refE =avg - (_cur_pop-_population)/(_population*_timeStep);
_last_pop = _cur_pop;
/* This is the part where walkers spawn and die */
int m,j;
_nCopies = 0;
for(i=0;i<_cur_pop;i++) {
m = floor(_walkers[i].Weight(_refE)+rnd());
if(m<3) m=3;
if(m==0) { /* The poor Walker dies */
if(_cur_pop>1) {
_walkers[i].Copy(_walkers[_cur_pop]);
i--, _cur_pop--;
} else {
cout << "WARNING :: Your population is dying!" << endl;
}
} else {
for(j=1;j<m;j++) {
_copies[_nCopies].Copy(_walkers[i]);
_nCopies++;
}
}
}
/* Adding the copies */
for(j=0;j<_nCopies; j++) {
_walkers[_cur_pop].Copy(_copies[j]);
_cur_pop++;
}
return 0;
}
template<class walker>
double DQMCSimulation<walker>::GetReferenceEnergy() {
return _refE;
}
template<class walker>
walker* DQMCSimulation<walker>::WalkerArray() {
return _walkers;
}
/*************************
* 1D Harmonic Oscillator
************************/
class DQMCHarmonic1DWalker : public DQMCWalker {
double _x;
public:
DQMCHarmonic1DWalker() {
_x=0.0;
}
int WalkNormal() {
double dt = sqrt(GetDeltaT());
_x+=NormalDistribution(1.0,0.0)*dt;
return 0;
}
double Potential() {
return 0.5*(_x*_x);
}
int Copy(DQMCHarmonic1DWalker w) {
_x = w._x;
return 0;
}
};
this is the main of the program
int main() {
srand ( time(NULL) );
int i,j, count;
double refE;
cout << "Hamonic 1D:" << endl;
DQMCSimulation<DQMCHarmonic1DWalker> simulation1(500,0.1);
refE = 0.0;
for(i=1; i<1000; i++) {
simulation1.Iterate();
refE += simulation1.GetReferenceEnergy();
if(i%50==0)
cout << refE/i << ", ";
}
return 0;
}
The first and easily noticeable problem is that You need to follow the Rule of Three/Five for DQMCSimulation class.