Cannot find my error

I'm writing a program for a class and cannot figure out my mistake. Can anyone help. the program is below:

//C++ Exercises and Solutions
//www.cppexercisesandsolutions.com
//C++ How to Program (8th Edition) By Paul Deitel, Harvey Deitel
//3.13
//main.cpp file
//10.07.2012

#include <cstdio>
#include <cstdlib>
#include <iostream>

using namespace std;

#include "Invoice.h"

int main()
{
// initialization with constructor
Invoice invoice1 ("Part_123", "one paper", -7, 2000);
Invoice invoice2 ("Part_234", "long", 20, 50000);

// output constructor results
cout << "\nNew invoice details: \nPart Number: " << invoice1.getPartNumber()
<< "\nDescription: " << invoice1.getPartDescription()
<< "\nQuantity: " << invoice1.getQuantity()
<< "\nPrice: " << invoice1.getPrice() << endl;

cout << "\nNew invoice details: \nPart Number: " << invoice2.getPartNumber()
<< "\nDescription: " << invoice2.getPartDescription()
<< "\nQuantity: " << invoice2.getQuantity()
<< "\nPrice: " << invoice2.getPrice() << endl;

// get price and quantity by get functions
int x1 = invoice1.getQuantity();
int y1 = invoice1.getPrice();
int x2 = invoice2.getQuantity();
int y2 = invoice2.getPrice();

// calculate invoice by getInvoiceAmount function
cout << "\n1 amount is " << invoice1.getInvoiceAmount ( x1, y1 ) << endl;
cout << "2 amount is " << invoice2.getInvoiceAmount ( x2, y2 ) << endl;

cout << endl;

// test program that using data entered by user
cout << "*** Test Program ***";

// variables
string p_Number;
string p_Desc;
int ppi;
int p_Quantity;

// get data from user
cout << "\nPlease enter Part Number: ";
cin >> p_Number;
cout << "Please enter Part Description: ";
cin >> p_Desc;
cout << "Please enter Price Per Item: ";
cin >> ppi;
cout << "Please enter Quantity: ";
cin >> p_Quantity;

//using set functions
invoice1.setPartNumber(p_Number);
invoice1.setPartDescription(p_Desc);
invoice1.setPrice(ppi);
invoice1.setQuantity(p_Quantity);

// using get functions, invoice amount function and output result
cout << "\nPart number is " << invoice1.getPartNumber();
cout << "\nPart description is " << invoice1.getPartDescription();
cout << "\nPrice is " << invoice1.getPrice();
cout << "\nQuantity is " << invoice1.getQuantity();
cout << "\nInvoice amount is " << invoice1.getInvoiceAmount(invoice1.getPrice(), invoice1.getQuantity());

}



//invoice.h file
//10.07.2012

#include <cstdio>
#include <cstdlib>
#include <iostream>

using namespace std;

class Invoice
{
public:
Invoice(string initPartNumber, string initPartDescription, int initQuantity, int initPrice);
void setPartNumber( string);
string getPartNumber();
void setPartDescription (string);
string getPartDescription();
void setQuantity( int );
int getQuantity();
void setPrice( int );
int getPrice();
int getInvoiceAmount(int, int);

private:
string partNumber;
string partDescription;
int quantity;
int price;
int invoiceAmount;
};



//Invoice.cpp file
//10.07.2012

#include <cstdio>
#include <cstdlib>
#include <iostream>

using namespace std;

#include "Invoice.h"

// initialization with constructor
Invoice::Invoice( string initPartNumber, string initPartDescription, int initQuantity, int initPrice)
{
setPartNumber( initPartNumber );
// cout << "Part Number set completed" << endl; // uncomment it if you want to see sequence

setPartDescription( initPartDescription );
// cout << "Description set completed" << endl; // uncomment it if you want to see sequence

// if number is positive
if (initQuantity >= 0)
{
setQuantity( initQuantity );
//cout << "Number set completed" << endl; // uncomment it if you want to see sequence
}
// if number is not positive it set as 0
if (initQuantity < 0)
{
quantity = 0;
cout << "Number can not be negative and set as 0" << endl;
}
// if number is positive
if (initPrice >= 0)
{
setPrice( initPrice );
// cout << "Price set completed" << endl; // uncomment it if you want to see sequence
}
// if number is not positive it set as 0
if (initPrice < 0)
{
price = 0;
cout << "Price can not be negative and set as 0" << endl;
}
}

//set function for Part Number
void Invoice::setPartNumber( string initPartNumber )
{
partNumber = initPartNumber;
}

//get function for Part Number
string Invoice::getPartNumber()
{
return partNumber;
}

//function for set desc
void Invoice::setPartDescription ( string initPartDescription )
{
partDescription = initPartDescription;
}

//function for get desc
string Invoice::getPartDescription()
{
return partDescription;
}

//function for set number
void Invoice::setQuantity( int initQuantity)
{
quantity = initQuantity;
}

//function for get number
int Invoice::getQuantity()
{
return quantity;
}

//function for set price
void Invoice::setPrice( int initPrice)
{
price = initPrice;
}

//function for get price
int Invoice::getPrice()
{
return price;
}

//function for get invoice amount
int Invoice::getInvoiceAmount( int iQuantity, int iPrice)
{
if((iQuantity<0)||(iPrice<0))
{
cout << "Incorrect args!" << endl;
}
else
{
invoiceAmount = iQuantity * iPrice;
}
return invoiceAmount;
}
220 lines of code, you want us to guess what/where the problem is ?
First use this syntax to enter your code on this forum:

http://www.cplusplus.com/articles/z13hAqkS/


Second, do you have an error and possible line where the error is occurring?

Third, it looks like you have your client code, implementation code, and class header file all together. Separating them could help you.
Hi,

Welcome to cplusplus :+)

Just some pointers to help you out for the future:

1. Please use code tags

http://www.cplusplus.com/articles/jEywvCM9/


2. If you have compiler errors, then please post them here verbatim. That saves us trying to do mind reading, or compiling it ourselves. We can explain what the errors mean.

3. Provide a description of where you think it might be going wrong.

4. Provide a description of the assignment question - so we can see what you are aiming for, at the moment we are guessing. I could write that program with much shorter code, but I imagine that your teacher wants you to have practice at doing things in different ways.

5. If you have runtime errors, then consider using a debugger. If using an IDE, there should be a GUI one built-in.

With classes, there is the concept of the invariant - which means that all the member variables have to maintain values that are sensible throughout the lifetime of the object. For example you have Quantity and Price which must always be positive.

So when you create an object, there are some different choices. One is to get the user input, validate it, then create the object with the valid values. Another way is to create the object with the input values, then in the constructor check the validity of them, then print out error messages and call the destructor if any of them are invalid. There are other ways such using assertions and exceptions - but I am guessing those topics may be a bit advanced at the moment.

Right now you have a bunch of trivial set functions, here is an example of a better way of doing the same thing with an initialiser list:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Invoice::Invoice( const std::string& initPartNumber,             // Use references for STL containers
                       const std::string& initPartDescription,        // use const for things that shouldn't change
                       const int              initQuantity,                   // must be positive
                       const int              initPrice)                       // must be positive and is whole dollar amount

      :    // colon introduces initialiser list
      partNumber        (initPartNumber),         // member variables are initialised here
      partDescription   (initPartDescription),
      quantity             (initQuantity),
      price                  (initPrice)              

{ // constructor
   if (quantity <= 0 || price <=0 ) {
        std::cout << "Error -  Price or Quantity must be greater than zero - destructor called\n"
        ~Invoice();
   }
   // invariants OK, assign values
  invoiceAmount = quantity * price;
}


So now you could get rid of all those set functions - unless your teacher wants you to have them (presumably so you can have practice calling them). With the case of having to update values of member variables after the object has been created, you could write an Update function, remember that a member function has direct access to member variables. Another example might for classes for various shapes, I would have functions such Move, Rotate, Scale etc, rather than just get / set functions.

So the idea here is to think about what needs to happen to an object, rather than blindly writing get / set functions for every member variable. Btw, this forum has had huge debates in the past about this topic, hopefully it won't turn into a marathon again ! :+|


It's also possible to get rid of the get functions as well :+) In your example, the values of the member variables don't change and there doesn't seem to be a requirement for the member variables to be accessed from outside the object. So you just write a PrintDetails function, that prints all the values nicely. Remember a member function has access to all the member variables.

If there is a requirement to access member variables values, then I don't have a problem with trivial accessor functions.

With your getInvoiceAmount function, it should just return the value, and shouldn't take any arguments. Validation and assignment should have been done earlier.

Hope this helps a bit :+D
Topic archived. No new replies allowed.