CSC262 Feb03

slide version

single file version

Contents

  1. Self Test, problem #9
  2. Assignment 4
  3. LineItem.h Design Output
  4. Implementation
  5. InvoiceTest
  6. Sample Output
  7. How to ... : 1
  8. How to ...: 2
  9. How to ...: 3
  10. How to ...: 4
  11. Bank Account Design
  12. Strings
  13. C Strings
  14. C Strings: Declarations
  15. C Strings: Operations
  16. String Length
  17. C Strings: Assignment
  18. C String: Dynamic C String
  19. C Strings: Comparison
  20. C Strings: Searching
  21. C Strings: Splitting
  22. Splitting Example
  23. C Strings: Additional Operations
  24. C Strings: I/O in C++
  25. C Strings: As Class Members
  26. C++ Strings
  27. C++ Strings: Operations

Self Test, problem #9[1] [top]

  1. The class Money has two data members: dollars and cents. A function that overloads operator+ that adds two Money values and returns a Money value representing their sum is to be written. If this function is declared in the Money class at (*) below, which of the declarations shown would be correct?

    	    class Money
                {
                   int dollars;
                   int cents;
                public:
                   Money();
                   Money(int d, int c);
    
                   // (*) Declare an overloaded operator+
                   ...
                };
    	  
    	    (1) Money operator+(const Money& m) const;
    	    (2) Money operator+(const Money& m1, const Money& m2);
    	    (3) friend Money operator+(const Money& m1, const Money& m2);
    	    (4) friend Money operator+(const Money& m1, const Money& m2) const;
    	  
    1. Any one of these would be correct
    2. Only (1)
    3. Only (2)
    4. Only (1) or (3)
    5. Only (2) or (3)
    6. Only (1) or (4)
    7. Only (2) or (4)

 

Assignment 4[2] [top]

Here is the design outut for one of the classes: Invoice.h

(What data members are needed?)


class Invoice
{
public:
  /**
   * Initialize an Invoice for up to maxItems LineItems
   */
  Invoice();
  Invoice(int maxItems);
  Invoice(const Address& addr, int maxItems);

  /**
   * Formats the invoice
   */
  string format();

  /**
   * Adds a line item for a product and quantity to
   * this invoice.
   */
  void add(const Product& p, int quantity);

};

LineItem.h Design Output[3] [top]


class LineItem
{
public:
  /**
   * Initialize LineItem
   */
  LineItem();
  LineItem(const Product& p, int quantity);

  /**
   * format the line item
   */
  string format();

  /**
   * get line item total amount
   */
  double getLineTotal();

};

Implementation[4] [top]

To implement the design:

In addition, we must provide tests for the class(es).

InvoiceTest[5] [top]

Here is a sample invoice test program:


int main()
{
  Address ezAddr("EZ Rental",
           "8384 Dempsey",
           "Brooklyn",
           "NY",
           "01234");

  Invoice ezInv(ezAddr, 10);

  ezInv.add(Product("Power Cleaner", 49.95), 1);
  ezInv.add(Product("PX Cleaner Fluid", 9.00), 8);
  ezInv.add(Product("M803 Vac Bags", 2.08), 10);

  cout << ezInv.format() << endl;
  
  return 0;
}

The responsibilities for formatting and printing the invoice are distributed over the classes as a result of the design phase. No one class has to do everything and so each class can be easier to understand and implement.

In general, this CRC technique can provide an effective way of modularizing a program using object oriented features. Classes are designed and Responsibilities are assigned to the chosen class objects with the goal of building a system according to specified requirements.

Sample Output[6] [top]

This test program should produce the invoice:

                         Invoice

EZ Rental
8384 Dempsey
Brooklyn, NY 01234

Description            Qty             Price     Total
------------------------------------------------------
Power Cleaner           1              $49.95    49.95
PX Cleaner Fluid        8              $ 9.00    72.00 
M803 Vac Bags	       10              $ 2.08    20.80

Amount Due: $142.75

      

How to ... : 1[7] [top]

How can you print the headings:

	Description       Qty       Price       Total
      

so that

  1. include <iomanip>
  2. Use cout << setw(25) to cause the next item output be in a field of 25 character positions
  3. cout.setf(ios::left, ios::adjustfield) causes an item that needs fewer character positions than the field to be placed in the left most positions (and padded with the fill character, i.e., blanks)
  4. cout.setf(ios::right, ios::adjustfield) causes an item that needs fewer character positions than the field to be placed in the right most positions (and padded with the fill character, i.e., blanks)

cout.setf(ios::left, ios::adjustfield);
cout << setw(15) << "Description";
cout.setf(ios::right, ios::adjustfield);
cout << setw(10) << "Qty"
     << setw(10) << "Price"
     << setw(10) << "Total" << endl;

How to ...: 2[8] [top]

How can you create a format string instead of printing the previous heading?

#include <sstream>

string format()
{
  stringstream ss;

  ss.setf(ios::left, ios::adjustfield);
  ss << setw(15) << "Description";
  ss.setf(ios::right, ios::adjustfield);
  ss << setw(10) << "Qty"
       << setw(10) << "Price"
       << setw(10) << "Total" << endl;

  return ss.str();

}
      

How to ...: 3[9] [top]

How can you print a line of 55 "-" without typing all 55 characters?

When an output value needs fewer character positions than the output field, the value is padding with the 'fill' character either on the left or on the right depending on the justification desired.

The fill character, by default, is a blank.

But you can change the fill character. For example, you can make the fill character be '-'.

Then to print 55 '-' characters:


cout.fill('-');
cout << setw(55) << "" << endl;
cout.fill(' ');



	
      

How to ...: 4[10] [top]

How do you print floats and doubles in fixed decimal format (not scientific notation) and with 2 decimal places?


cout.setf(ios::fixed);
cout.precision(2);
	
      




      

Bank Account Design[11] [top]

An object oriented program is to be designed that can print bank statement for a checking account or a savings account. The printed output of each kind of statement will contain the customer's name and address and account number. The current balance will be printed on a separate line. Then each detail line of a statement will show the date, deposit or withdrawal (in separate columns), the amount of the transaction, and the balance after the transaction is processed. For a savings account, the interest earned depends on the interest rate which is the same for all savings accounts. The earned interest is computed simply as the monthly interest rate times the minimum balance in the account for the month. For a checking account, there is no service charge for the first 10 checks. After that there is a service charge of .05 per check. The service charge is shown on a separate line on the checking account statement.

Use the CRC (classes, responsibilities, collaborators) technique to propose a list of classes that could be useful in writing this program. For each of your classes, give:

Strings[12] [top]

Two kinds of strings:

C strings are just ordinary arrays of char, with the last char being the character with all bits 0. This can be represented using single quotes as '\0', but not '0'. The '0' is the character for the digit 0.

Here are the 8 bit patterns for each character:

character 8 bit Representation decimal integer value
'\0' 0000 0000 0
'0' 0011 0000 48
'1' 0011 0001 49
'2' 0011 0010 50

C Strings[13] [top]

Since a C string is not really a separate type, but just a array of chars (special because the last char should be '\0'), declarations and operations are defined and implemented terms of char arrays.

C Strings: Declarations[14] [top]

	char s1[] = {'C', 'a', 't', '\0'};
	char s2[] = "Cat";
	char s3[4] = "Cat";


	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;

      

All 3 print the same output:

	Cat
      

C Strings: Operations[15] [top]

String Length[16] [top]

	#include <cstring>
	int strlen(const char *s);
      

Example:


int main()
{
  char s1[4] = {'C', 'a', 't', '\0'};
  int length;

  length = strlen(s1);
  cout << s1 << endl;
  cout << "length = " << length << endl;

}
Output: 3 (not 4)

C Strings: Assignment[17] [top]

	char * strcpy(char *dest, const char *source);
      

The 'const' means something can't be changed. What is that something?


int main()
{
  char s[] = "Hello, World!";
  char m[50];

  strcpy(m, s);

  cout << m << endl;

}
Output: Hello, World!

C String: Dynamic C String[18] [top]


int main()
{
  char s[132];

  cout << "Input a sentence on one line" << endl;
  cin.getline(s,132);
  char *m = new char[strlen(s) + 1];

  strcpy(m, s);

  cout &lt;&lt; m &lt;&lt; endl;
  ...

  delete [] m;

}
Output: (the input sentence)

C Strings: Comparison[19] [top]

	int strcmp(const char *s1, const char* s2);
      
Return value of
strcmp(str1, str2)
Meaning
less than 0 str1 is less than str2
equals 0 str1 is equal to str2
greater than 0 str1 is greater than str2

C Strings: Searching[20] [top]

There are functions to search for the first occurrence of a given char in a string or to search for the first occurence of a string as a substring in another string.

	char * strchr(const char *str1, int ch);

        char * strstr(const char *str1, const char *str2);
      

Both return NULL if the second parameter is not found in str1.

C Strings: Splitting[21] [top]

A handy function for splitting a string into substrings is

	char * strtok(char *str1, const char *delims);
      

The strtok function returns a pointer to the next .token. in str1, where str2 contains the delimiters that determine the token. strtok returns NULL if no token is found.

In order to convert a string to tokens, the first call to strtok should have str1 point to the string to be tokenized. All calls afterwards should have str1 be NULL.

Splitting Example[22] [top]

...
#include <cstring>

int main()
{
  string line;
  cout << "\nEnter a line with comma separated values" << endl;
  getline(cin, line);
  const char *s = line.c_str();
  char *p = new char[strlen(s) + 1];
  strcpy(p, s);
  char *q;

  q = strtok(p, ";");
  while( q != NULL ) {
    cout << q << endl;
    q = strtok(NULL, ";");
  }

  return 0;
}
Input Line: Jason R Bloch;5512 Garden Lakes Dr.;Flushing, NY 01234

Output:
Jason R Bloch
5512 Garden Lakes Dr.
Flushing, NY 01234

C Strings: Additional Operations[23] [top]

C Strings: I/O in C++[24] [top]


int main()
{
  string line;
  ifstream ifs;
  string fname;

  cout << "Address file name: ";
  cin >> fname;
  ifs.open(fname.c_str());
  if (!ifs.is_open()) {
    cout << "Unable to open input file '" << fname << "'" << endl;
    exit(0);
  }
  // Now process the file
  ...
}

C Strings: As Class Members[25] [top]


class Employee
{
  char *name;
  double salary;
public:
  Employee();
  Employee(char nm[], double sal);
  Employee(const Employee& other);

    
  const char * getName() const;
  double getSalary() const;

  void setSalary(double newSalary);

  void operator=(const Employee& other);

  ~Employee();
};

Implementation of second constructor and the destructor:


Employee::Employee(char nm[], double sal)
{
  name = new char[strlen(nm) + 1];
  strcpy(name, nm);
  salary = sal;
}

Employee::~Employee()
{
  delete [] name;
}




      

C++ Strings[26] [top]

C++ strings are a new type: string.

This type is defined by the string class.

There are many member functions and also many overloaded non-member operators.

The string class has its own assignment operator, copy constructor, and destructor. So in general, you don't have to manage memory for C++ strings

C++ Strings: Operations[27] [top]