Thread: Bank Account System in C++ using Classes and Data Encapsulation

  1. #1
    Registered User
    Join Date
    Nov 2004
    Posts
    73

    Bank Account System in C++ using Classes and Data Encapsulation

    Hi everyone,

    I have run into problems with this program involving a customer bank account management system on C++ using a class.

    Here is a description of what the program should do:

    In a header file, I need to hold the definition of a class. This class will store information about a customer at a bank. The class must contain data members for Customer Name, Street Address, City, Postal Code and account balance. I need to write a Constructor function that will initialize each of the data members. I need to add methods to: define the data for the account, allow money to be deposited into the account, allow money to be withdrawn from the account and show all data stored for the account (name, address, balance). Validate the input from the user. If bad data is entered, prompt again. The postal code must be in the form L#L#L#. I need some assistance on checking for invalid postal codes as well.

    Then, in a separate .cpp file I will have the main routine that will test the class in the header file. The program should be able to handle up to 10 customers which is why I've made an array of 10 instances as you'll see below.

    First problem was that I was receiving bad information on the first run through of displaying the user-inputted data. Second problem I had was that the program would crash after entering information for one of the five private data members.

    Here is my code up to this point. I've put the whole thing together even though the main routine is supposed to be in a .cpp file and the class definition in a .h header file. I commented out a main menu which will eventually allow the user to choose an option and then go through only that option and then return to the main menu once complete but first I want to make sure all the class methods work OK and currently they are not.

    Here is my code so far:

    Code:
    #include  <iostream>
    #include  <conio.h>
    #include  <stdlib.h>
    
    
    class Customer {
    
       private:                          // data members (properties)
          char *name;                    
          char *address;
          char *city;
          char *pcode;
          float acc_bal;
    
       public:
          Customer:: Customer() {              // constructor
             name = NULL;
             address = NULL;
             city = NULL;
             pcode = NULL;
             acc_bal = 0.00;
          }
    
          void addcust() {                          // add customer method
             cout << "\nEnter your name: ";    cin >> name;
             cout << "\nEnter your address: ";   cin >> address;
             cout << "\nEnter your city: ";      cin >> city;
             cout << "\nEnter your postal code: ";    cin >> pcode;
             cout << "\nEnter current account balance: ";    cin >>   
             acc_bal;
          }
    
          void deposit(float bal) {               // deposit money method
             float dep;
             cout << "\nEnter amount to be deposited: ";    cin >> dep;
             bal = bal + dep;
             acc_bal = bal;
          }
    
    
          void withdraw(float bal) {          // withdraw money method
             float wdraw;
             cout << "\nEnter amount to be withdrawn: ";    cin >>  
             wdraw;
             bal = bal - wdraw;
             acc_bal = bal;
          }
     
          void showdata() {                   // show data method
             cout << "Name: " << name;
             cout << "\nAddress: " << address;
             cout << "\nCity: " << city;
             cout << "\nPostal Code: " << pcode;
             cout << "\nAccount Balance: $" << acc_bal << endl;
          }
    
    };
    
    int main() {
    
    /*
       cout << "\t\t\n\n" << "Main Menu";
       cout << "\t\n\n" << "Select by letter:";
       cout << "\t\n" << "a - Add a customer.";
       cout << "\t\n" << "d - Deposit money.";
       cout << "\t\n" << "w - Withdraw money.";
       cout << "\t\n" << "s - Show Account Information.";
       cout << "\t\n" << "q - Quit Application.\n\n";
       cout << "\t" << "Choice: ";
    */
    
       Customer cust[10];         // array of 10 instances of customer
       int i;
       for (i = 0; i < 10; i++) {
          cust[i].getdata();
          cust[i].showdata();
       }
    }
    Basically, I'm trying to find out why the program is crashing on me and how I can change the methods to reflect the correct data because I believe there is something incorrect about my logic here.

    Any help or assistance would be greatly appreciated. Thanks.

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Does that compile? I don't see Customer.getdata() anywhere (called from main()). Or did you remove it to make the posting shorter?

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    You should be using the standard C++ string class in <string> instead of C style character arrays. Your crash is because you aren't handling the strings correctly. Your name, address, city and pcode variables point to NULL when you construct a new object, and you never create memory for them.

    If you cannot use the string class because of class requirements, then you need to allocate space for your char* variables, and you also need to disable the copy constructor and copy assignment operator so you don't get mysterious crashes in the future.

  4. #4
    Registered User
    Join Date
    May 2005
    Posts
    73
    Just a bit of advice.

    - I wouldn't recommend the cout and cin statements inside of your class. This kindof defeats the purpose of a class. For showdata() function this is ok, but for input you should gather that in main() and pass the variables "name" "address" etc. into your addcust() function.

    - In your deposit/withdraw function you are passing in a value called "bal". This has to be passed in and directly added or subtracted from acc_bal.

    - Usually when using pointers in a class it is advisable to create a destructor to free the space when the class variable goes out of scope. Otherwise crashes probably will occur. Perhaps you should try "string" instead of "char *". This would eliminate the need for a destructor.

    Anyways here is some revised code that you can examine if you want.

    Code:
    #include  <iostream.h> // <iostream> -> <iostream.h>
    // #include  <conio.h> // Include not required.
    // #include  <stdlib.h>	// Include not required.
    
    class Customer 
    {
      private:                         
        char *name;                    
        char *address;
        char *city;
        char *pcode;
        float acc_bal;
    
      public:
        Customer:: Customer() 
        {            
          name = new char[20];	// name = NULL will cause crash.  Need to allocate
          address = new char[25];	// address = NULL will cause crash. Need to allocate.
          city = new char[15];	// city = NULL will cause crash.	Need to allocate
          pcode = new char[10];	// pcode = NULL will cause crash.	Need to allocate.
          acc_bal = 0.00;
        }
    
        Customer::~Customer() 
        {	// IF pointers are used you need a destructor to free memory allocated or else memory leaks.
          delete [] name;
          delete [] address;
    	delete [] city;
    	delete [] pcode;
        }
    
         void addcust() 
        {                          
          cout << "\nEnter your name: ";    cin >> name;
          cout << "\nEnter your address: ";   cin >> address;
          cout << "\nEnter your city: ";      cin >> city;
          cout << "\nEnter your postal code: ";    cin >> pcode;
          cout << "\nEnter current account balance: ";    cin >> acc_bal;
         }
    
        void deposit(/*float bal*/)  // Your function accepts a value that is never used. float bal
        {              
          float dep;
          cout << "\nEnter amount to be deposited: ";    cin >> dep;
          // bal = bal + dep; // Line not needed.
          acc_bal = acc_bal + dep;	// acc_bal = bal does nothing.
         }
    
        void withdraw(/*float bal*/) // Your function accepts a value that is never used. float bal
        {         
          float wdraw;
           cout << "\nEnter amount to be withdrawn: ";    cin >> wdraw;
           // bal = bal - wdraw;	// Line not needed.
           acc_bal = acc_bal - wdraw; // acc_bal = bal does nothing. Change + to -
        }
     
         void showdata() 
        {                  
          cout << "Name: " << name;
          cout << "\nAddress: " << address;
          cout << "\nCity: " << city;
          cout << "\nPostal Code: " << pcode;
          cout << "\nAccount Balance: $" << acc_bal << endl;
        }
    };
    
    int main() 
    {
      Customer cust[10];
      
      //int i;	// Move declaration into for loop.
      
      for (int i = 0; i < 10; i++) 
      {
        cust[i].addcust(); // Change function call to addcust(); getdata() doesn't exist.
        cust[i].showdata();
      }
    
      return 0; // int main() needs to return an integer.
    }
    Below is an example of how you should really be utilizing your class methods.
    Code:
    int main()
    {
      for(int i = 0; i < 10; i++)
      {
        cout << "\nEnter your name: ";    cin >> name;
        cout << "\nEnter your address: ";   cin >> address;
        cout << "\nEnter your city: ";      cin >> city;
        cout << "\nEnter your postal code: ";    cin >> pcode;
        cout << "\nEnter current account balance: ";    cin >> acc_bal;  
    
        cust[i].addcust(name, address, city, pcode, acc_bal);
      }
    
      cout << "\nEnter amount to be deposited: ";    cin >> dep;  
      cust[0].deposit(dep);
    }
    
    void customer::deposit(float bal) 
    { 
      acc_bal = acc_bal + bal;
    }
    
    void customer::addcust(char *n, char *a, char *c, char *p, float bal) 
    {                          
      name = n;
      address = a;
      city = c;
      pcode = p;
      acc_bal = bal;
    }
    Just for future reference.

  5. #5
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    > #include <iostream.h> // <iostream> -> <iostream.h>
    Bad advice, Deo. Don't advise the use of out-dated headers in favor of standard headers. Most current compilers don't even support the non-standard header (<iostream.h>).

    Also, your code will lead to crashes, or at the very least bad data. In your version of addcust, you are copying the pointer to the character array, so every time the for loop in main gets another string from the user, all the data held in previous customer objects will be modified as well. You should be making a copy of the data in addcust. You should also be careful of the user typing in data that is longer than the size of the strings you allocated in the constructor. Of course, the C++ string class takes care of that for you.

  6. #6
    Registered User
    Join Date
    Nov 2004
    Posts
    73

    Re:

    Thanks for all the suggestions guys.

    I won't get a chance to continue working on this until late tomorrow so if anyone has anything else they would like to add or mention about this problem, go right ahead.

    Thanks again to all.

  7. #7
    Registered User
    Join Date
    May 2005
    Posts
    73
    Quote Originally Posted by Daved
    > #include <iostream.h> // <iostream> -> <iostream.h>
    Bad advice, Deo. Don't advise the use of out-dated headers in favor of standard headers. Most current compilers don't even support the non-standard header (<iostream.h>).
    Oh fine...
    Code:
    #include <iostream>
    using  std::cout;
    using  std::cin;
    Also, your code will lead to crashes, or at the very least bad data. In your version of addcust, you are copying the pointer to the character array, so every time the for loop in main gets another string from the user, all the data held in previous customer objects will be modified as well. You should be making a copy of the data in addcust. You should also be careful of the user typing in data that is longer than the size of the strings you allocated in the constructor. Of course, the C++ string class takes care of that for you.
    Yeah i know. I didn't mean for that code to be taken literally. I was just emphasizing that customer info should be gathered in main then passed into a class function or constructor to be assigned instead of being gathered in the CUSTOMER CLASS to facilitate an application independent CLASS.
    Last edited by Deo; 06-01-2005 at 01:35 AM.

  8. #8
    Registered User
    Join Date
    Nov 2004
    Posts
    73
    yeah I think what I need to do is put the class in the header file and then in the main routine which is in a separate .cpp file, I need to get all the information from the user. This is supposed to be a menu-driven program so I'll need to put the menu probably in the main C++ program as well.

    This may sound like a strange question but is there much difference between programming menus in C and C++? Anyway, I guess I'd have to use cout for displaying and cin.get() for getting a letter option from the user but the problem with that is with cin.get(), it forces the user to hit enter after entering the letter. Can I use something like getch() for that which will automatically execute the menu option when the letter is pressed instead of having to hit enter after?

    Keep posting comments, suggestions or advice if you have any. I appreciate all the advice. I'll be working on this a little bit at a time and hopefully I'll have it completed by the weekend.

  9. #9
    Registered User
    Join Date
    Nov 2004
    Posts
    73

    Re: Postal Code Validation

    Well my bank program using classes is working a lot better now.

    I need some help though on how to validate a Canadian postal code entry to ensure that it's in 'letter-number-letter-number-letter-number' format in C++. I think I know that I need to check the postal code char by char but I'm not sure of how to actually code it.

    Here is my current program:

    Code:
    #include  <iostream>
    #include  <conio.h>
    #include <stdlib.h>
    
    class Customer {
    
       private:
          char name[20];
          char address[30];
          char city[20];
          char pcode[6];
          float acc_bal;
    
       public:
          Customer:: Customer() {              // constructor
             acc_bal = 0.00;
          }
    
          void getdata() {
             cout << "\nEnter your name: ";    cin >> name;
             cout << "\nEnter your address: ";   cin >> address;
             cout << "\nEnter your city: ";      cin >> city;
             cout << "\nEnter your postal code: ";    cin >> pcode;
             cout << "\nEnter current account balance: ";    cin >> acc_bal;
          }
    
          void deposit() {
             float dep;
             cout << "\nEnter amount to be deposited: ";
             cin >> dep;
             acc_bal += dep;
          }
    
          void withdraw() {
             float wdraw;
             cout << "\nEnter amount to be withdrawn: ";    cin >> wdraw;
             acc_bal -= wdraw;
          }
    
          void showdata() {
             cout << "Name: " << name;
             cout << "\nAddress: " << address;
             cout << "\nCity: " << city;
             cout << "\nPostal Code: " << pcode;
             cout << "\nAccount Balance: $" << acc_bal << endl;
          }
    
    };
    
    int main() {
    
       char choice;
       int flag = 0;
       int count = 0;
       int recnum;
       Customer cust[10];
    
       while (flag == 0) {
          cout << "\t\t\n\n" << "Main Menu";
          cout << "\t\n\n" << "Select by letter:";
          cout << "\t\n" << "a - Add a customer.";
          cout << "\t\n" << "d - Deposit money.";
          cout << "\t\n" << "w - Withdraw money.";
          cout << "\t\n" << "s - Show Account Information.";
          cout << "\t\n" << "q - Quit Application.\n\n";
          cout << "\t" << "Choice: ";
          choice = getche();
          switch(choice) {
             case 'a':
                system("cls");
                if (count > 10) {
                   cout << "Can't add anymore records. Press any key to return to main menu.";
                   getche();
                   break;
                }
                count += 1;
                cust[count].getdata();
                system("cls");
                break;
    
             case 'd':
                system("cls");
                cout << "\nEnter customer number: ";
                cin >> recnum;
                cust[recnum].deposit();
                system("cls");
                break;
    
             case 'w':
                system("cls");
                cout << "\nEnter customer number: ";
                cin >> recnum;
                cust[recnum].withdraw();
                system("cls");
                break;
    
             case 's':
                system("cls");
                cout << "\nEnter customer number: ";
                cin >> recnum;
                cust[recnum].showdata();
                getche();
                system("cls");
                break;
    
             case 'q':
                flag = 1;
                break;
    
             default:
                cout << "\nInvalid selection. Press a key to return to main menu.";
                getche();
          }
    
          if (flag == 1) {
             break;
          }
    
       }
       return 0;
    }
    So if anyone has any advice on how to validate a postal code then please post a message on this thread. It would be much appreciated.

    Thanks.

  10. #10
    Registered User
    Join Date
    May 2005
    Posts
    73
    Code:
    bool flag = false;
    
    while(flag == false)
    {
      cout << "\nEnter your postal code: ";    cin >> pcode;
      
      for(int i = 0; i < 6; i++)  // Go through 6 digits.
      {
        if(i % 2 == 0)  // If even digit. (0, 2, 4, 6)
       {
          if(pcode[i] < 48 || pcode[i] > 57) // Is digit a #?
          {
             flag = false;  // Current digit garbage.
             break;  // Get user input again.
           }
           else
              flag = true;  // Current digit OK. Proceed.
       }
        else  // If odd digit (1, 3, 5)
        {
           if(pcode[i] < 65 || pcode[i] > 90)  // Is digit A-Z ?
           {
              flag = false; // Current digit garbage.
              break;  // Get user input again.
            }
            else
               flag = true;  // Current digit OK. Proceed.
        }
      }
    }
    Something like this may give you a guide.. Don't copy and paste as I just wrote this up real quick.. probably won't work.

    1. Prompt and get user input.
    2. Go through each value in the postal code one by one.
    3. If even digit (i.e. 0, 2, 4, 6) check to see if it is a #. Compares digit to make sure it is in the range of 48-57 (Ascii values for 0-9).
    4. If invalid set flag to false and break for loop. (Goto step 1).
    5. Otherwise set flag to true and go to next digit in the pcode.

    1. Prompt and get user input.
    2. Go through each value in the postal code one by one.
    3. If odd digit (i.e. 1, 3, 5) check to see if it is a letter. Compares digit to make sure it is in the range of 65-90 (Ascii values for A-Z capital only not lowercase).
    4. If invalid set flag to false and break for loop. (Goto step 1).
    5. Otherwise set flag to true and go to next digit in the pcode.

    If all digits are ok then the while loop will not repeat and program will proceed. However, if one digit is bad it immediately reprompts for pcode. An error code could be displayed to user to inform whats going on..

    Code:
    pcode[i] < 65;
    I'm kinda sure 65 will be ascii, but so long since i used this. Might have to call a function that converts integer to ascii.. maybe someone can help u with this..
    Last edited by Deo; 06-02-2005 at 08:20 PM.

  11. #11
    Registered User
    Join Date
    Nov 2004
    Posts
    73
    It's funny you mentioned that Deo because there was a time when I used to know the ASCII table like the back of my hand but it's been a while since I've needed it for anything but I do remember 65-90 being 'A-Z'. Your step process in validating the postal code makes sense though. Thanks. I'm pretty close to wrapping this program up now.

  12. #12
    Registered User
    Join Date
    Nov 2004
    Posts
    73

    Re:

    One other thing, I want to place the Customer class in a separate header file and not as part of the main program so that it can be used with other programs as well. How can I do that so that it works in conjunction with the other programs? I tried to do that while putting in the #include statement for the header file but it wouldn't work. Do I need to change anything in compiler options or should that work with just the #include statement of the header file?

    I want to clear that up because I was getting a compile error when trying to put the class as a separate header file to be used in this program. So if anyone knows anything about this, let me know.

    Thanks.

  13. #13
    Registered User
    Join Date
    May 2005
    Posts
    73
    Main.cpp
    Code:
    #include "Customer.h"
    
    int main() 
    {
    	return 0;
    }
    Customer.h (Definition file)
    Code:
    //********************************CUSTOMER.h*****************//
    
    #ifndef customer_h
    #define customer_h
    
    class Customer {
    
       private:
          char name[20];
          char address[30];
          char city[20];
          char pcode[6];
          float acc_bal;
    
       public:
          Customer();
          void getdata();
          void deposit();
          void withdraw();
          void showdata();
    };
    
    #endif
    Customer.cpp (Specification/Implementation/etc..)
    Code:
    //******************************Customer.cpp********************//
    
    #include "Customer.h"
    #include <iostream>
    
    using std::cout;
    using std::cin;
    
    Customer::Customer() 
    {              // constructor
      acc_bal = 0.00;
    }
    
    void Customer::getdata() 
    {
    cout << "\nEnter your name: ";    cin >> name;
    cout << "\nEnter your address: ";   cin >> address;
    cout << "\nEnter your city: ";      cin >> city;
    cout << "\nEnter your postal code: ";    cin >> pcode;
    cout << "\nEnter current account balance: ";    cin >> acc_bal;
    }
    
    void Customer::deposit() 
    {
      float dep;
      cout << "\nEnter amount to be deposited: ";
      cin >> dep;
      acc_bal += dep;
    }
    
    void Customer::withdraw() 
    {
      float wdraw;
      cout << "\nEnter amount to be withdrawn: ";    cin >> wdraw;
      acc_bal -= wdraw;
    }
    
    void Customer::showdata() 
    {
      cout << "Name: " << name;
      cout << "\nAddress: " << address;
      cout << "\nCity: " << city;
      cout << "\nPostal Code: " << pcode;
      cout << "\nAccount Balance: $" << acc_bal << std::endl;
    }
    No compiler setting changes should be needed as long as Customer.h is in same directory as your program.

    Can just add all three files to your project and all should work fine..
    Last edited by Deo; 06-03-2005 at 01:15 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. I need the code of few programs in c++.plzzzzz help...plzzz
    By NAVINKR20 in forum C++ Programming
    Replies: 1
    Last Post: 05-08-2009, 09:13 AM
  2. Change 2 classes into 1, possible?
    By sugie in forum C++ Programming
    Replies: 6
    Last Post: 12-16-2005, 10:14 PM
  3. Classes with Other Classes as Member Data
    By njd in forum C++ Programming
    Replies: 2
    Last Post: 09-27-2005, 09:30 AM
  4. Replies: 3
    Last Post: 05-25-2005, 01:50 PM
  5. C Programming Question
    By TK in forum A Brief History of Cprogramming.com
    Replies: 13
    Last Post: 07-04-2002, 07:11 PM