Solved

C++ Database

Posted on 2004-04-19
16
201 Views
Last Modified: 2010-04-02
Hi,

I have program which basically acts like a bank.  It holds a user's account information, and transaction log.  It also allows users to withdrawal money, deposit, etc.  I need to keep track of all transactions.  Currently I use a file "1234.txt" which is the user's account number plus .txt, to hold the user's account information.  Then below it, is where the transaction logs will be held.  Here is what the file looks like...

1234
700
1234
Joe
L
Smith
*
1256
0
50
500
*
1333
1
200
700
*

The first section is..

Account Number
Balance
Pin Number
First Name
Middle Inital
Last Name

The other sections are...

Time code
Transaction Type
Transaction Amount
Ending Balance

I created an array to hold the input...

char transRecords[100][50];

This will hold a max of 20 records (five fields in each record because there is a * after each log).  I am tryign to load the information from the file into the array with this code...

char temp[50];
      int i = 0;
      
      ifstream infile; //Creates infile

      //Tries to open the file.  If it does not exist, it does not create one.
      infile.open(acctFile, ios::in|ios::nocreate);

      do {

            infile >> temp; //used for * after account information

      } while (temp[0] != '*');

      do {

            infile >> transRecords[i];
            ++i;
            cout << "H";

      } while (infile.eof == 0);

      infile.close();

      transRecordsSize = i;

      cout << i;
      pause();

The code doesn't execute.  The program just bombs out.  Any ideas on what I am doing wrong?

Ryan

0
Comment
Question by:RySk8er30
  • 8
  • 7
16 Comments
 
LVL 30

Expert Comment

by:Axter
ID: 10860374
You don't have a test in your code, to determind if the file is open successfully or not.

You don't have a condition in your second do-while to determind if you went pass the size of transRecords.
Try adding more logic that will check for these conditions.

Also try stepping through the code with the debugger to dertermind when you're code fails.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10860675
Try this:

     char temp[512] = ""; // 50 is nothing
     int i = 0;
     
     ifstream infile; //Creates infile

     //Tries to open the file.  If it does not exist, it does not create one.
     infile.open(acctFile, ios::in|ios::nocreate);
     if (!infile.is_open())
     {
           cout << " open failed " << endl;
           return;
      }
      while  (!infile.eof() && i < 100)
     {
          infile >> temp; //used for * after account information
          if (temp[0] == '*')
               continue;
          if (strlen(temp) >= 50)
              temp[50] = '\0';
          strcpy(transRecords[i], temp);
          i++;
     }

     infile.close();

     transRecordsSize = i;

     cout << i;
     pause();


Regards, Alex
0
 

Author Comment

by:RySk8er30
ID: 10868027
Hi,

I know the file exists and opens because the first part of the code...

do {

          infile >> temp; //used for * after account information

     } while (temp[0] != '*');

...works.  It's this part...

do {

          infile >> transRecords[i];
          ++i;
          cout << "H";

     } while (infile.eof == 0);

..that is giving me a problem.  I think it's my two dimentional array.

Any ideas?

Ryan




0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10868194
The first loop runs till the first '*' line occurs ignoring all lines before.

The second loop has a wrong while condition:

    while (infile.eof == 0);

must be changed to


    while (!infile.eof());

You should take the code i posted from above.

Regards, Alex





0
 

Author Comment

by:RySk8er30
ID: 10868797
Hi,

I'm still having trouble.  Here is the whole class..

<code>
#include "Time.h" //used for dateTime
#include "Utility.h" //used for lower(), ClearScreen
#include <iomanip.h> //used for setw()
#include <io.h> //used for eof
#include <fstream.h> //used for ifstream()

class TransDatabase { //Class which holds all transaction records

public:

      TransDatabase(); //Constructor
      ~TransDatabase(); //Destructor
      void displayTransLog(char *accountFile, int accountNum); //Displays transaction logs
      void inputTransRecord(char *acctFile, int type, double amount, double endingBalance); //Adds record to transaction log
      void loadTransactionLog(char *accountFile); //Loads transaction log into an array

private:

      Time dateTime;
      char time[50];
      int type;
      double amount;
      double endingBalance;
      char transRecords[100][50];
      int transRecordsSize;

}; //End TransDatabase class

TransDatabase::TransDatabase() { //Constructor

      time[50] = '\0';
      type = 0;
      amount = 0;
      endingBalance = 0;
      transRecordsSize = 0;

} //End Constructor

TransDatabase::~TransDatabase() { //Destructor

} //End Destructor

void TransDatabase::displayTransLog(char *accountFile, int accountNum) { //Displays transaction logs

      int i = transRecordsSize;
      
      //Sets up screen for transaction log display
      ClearScreen;
      lower();
      center("Transaction Log:");
      cout << setw(38) << accountNum << endl;
      cout << endl;

      //This will loop through the array, printing out each item until it has reached the max number
      for (int n = 0; n = i; n += 5) {
            cout << transRecords[n] << setw(5)
                   << transRecords[n + 1] << setw(5)
                   << setiosflags(ios::fixed) << setprecision(2) << transRecords[n + 2] << setw(5)
                   << setiosflags(ios::fixed) << setprecision(2) << transRecords[n + 3] << endl << endl;
      }

      pause();
      ClearScreen;
      
} //End displayTranslog

void TransDatabase::inputTransRecord(char *acctFile, int type, double amount, double endingBalance) { //Adds record to transaction log

      //Go to the end of the file

      Time t;
      
      //Write the information to the end of the file
      ofstream outfile(acctFile, ios::out);
      outfile << t.getTimeCode() << endl;
      outfile << type << endl;
      outfile << amount << endl;
      outfile << endingBalance << endl;
      outfile << "*" << endl;
      outfile.close();

} //End inputTransRecord

void TransDatabase::loadTransactionLog(char *acctFile) {

      char temp[50] = "";
      int i = 0;
      
      ifstream infile; //Creates infile

      //Tries to open the file.  If it does not exist, it does not create one.
      infile.open(acctFile, ios::in|ios::nocreate);

      do {

            infile >> temp; //used for * after account information

      } while (temp[0] != '*');

      do {

            infile >> transRecords[i];
            ++i;
            cout << "H";

      } while (!infile.eof());

      infile.close();

      //transRecordsSize = i;

      //cout << i;
      pause();

} //End loadTransactionLog

</code>

Here is where it is called...

<code>

void Account::verifyAcct() {  //Verifies account information

      /*

      Function Name: verifyAccount()
      Purpose: Verifies account information
      Parameters:
            Input: none
            Input & Output: none
            Output: none
      Return Value: void
      Data Members Accessed: acctNum, balance, firstName, middleInital, lastName, pin, acctFile
      Data Members Modified: acctNum, balance, firstName, middleInital, lastName, pin, acctFile
      Non-local Variables Used: none
      Functions Called: lower(), center(), getNumOnly(), getPin(), pause()

      */
      
      //Local Variables
      bool exit = false; //used to exit loop
      int pinFile = 0; //sets default pinFile number

      do {

      //prompts user for account number/pin, gets account number/pin

      lower();
      center("Please enter your four digit account number: ");
      cout << endl << setw(37) << " ";
      acctNum = getNumOnly();
      cout << endl << endl;
      center("Please enter your four digit pin number: ");
      cout << endl << setw(37) << " ";
      pin = getPin();

      _itoa(acctNum, acctFile, 10); //Puts value of acctNum into acctFile (and converts to string)

      strcat(acctFile, ".txt"); //Adds ".txt" to string

      ifstream infile; //Creates infile

      //Tries to open the file.  If it does not exist, it does not create one.
      infile.open(acctFile, ios::in|ios::nocreate);
      
      //If the account does not exist, output "Invalid account number..."
      
      if (!infile) {

            ClearScreen;
            lower();
            center("Invalid account number...");
            cout << endl << endl;
            pause();
            ClearScreen;

      } else { //Input information

            infile >> acctNum;
            infile >> balance;
            infile >> pinFile;
            infile >> firstName;
            infile >> middleInital;
            infile >> lastName;
            //Closes the file
            infile.close();

            transDatabase.loadTransactionLog(acctFile);

            if (pinFile != pin) { //If pin does not match file's pin, output "Invalid pin number..."

                  ClearScreen;
                  lower();
                  center("Invalid pin number...");
                  cout << endl << endl;
                  pause();
                  ClearScreen;

            } else { //If pin matches exit loop
                  
                  exit = true;

            }

            

      }

      } while (!exit); //end loop

} //end verifyAccount()

</code>

Any ideas?

Ryan
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10869579
Do you mind telling me what troubles you have?

I can see that you still have that first loop that runs to the first '*' line. That loop will eat all personal data from your input file:

1234
700
1234
Joe
L
Smith
*

I've seen that you did read all these data before, so it should work. But there are still lines containing a '*'  that don't get filtered. You are reading directly to char buffers that are only 50 bytes in size. If you got a longer input line, maybe spaces, your prog may crash. Better read to a real big buffer, check length, and copy a maximum of 49 chars to the transRecords buffers. It also crashes if it reads more than 100 lines.

Can you tell me where your program crashes and how many lines it had read before?

I couldn't compile your prog as there are some headers and global variables missing. You should post all sources and input file if you want us (me) to verify your tests.

Regards, Alex

0
 

Author Comment

by:RySk8er30
ID: 10869978
Hi,

The program reads all the personal data (up to the * fine).  After that it does not read any data.  It seems to crash during the second loop.  There are only 10 more lines, and each item is less than 50 characters.

If you provide an e-mail address, I can send my source code.

Ryan
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10870162
>> After that it does not read any data    

But the second loop reads til end of file. And it reads directly to 50 char buffers whithout any bounds-checking.

   do {

          infile >> transRecords[i];
          ++i;
          cout << "H";

     } while (!infile.eof());


Change it to that, just to make sure that thre isn't a courrupt input line

   char buffer[512];
   do {

          infile >> buffer;
          if (strlen(buffer) >= 50)
              buffer[49] = '\0';          // set length to 49 maximum

          strcpy(transRecords[i], buffer);
          ++i;
          // cout << "H"; ????
          cout << i << " " << buffer << endl;

     } while (i < 50 && !infile.eof());


You may send sources and input file using a zip file to info@sbsweb.info. Please give feedback here at EE if you had sent it as i have to fetch it from another mail server.

Regards, Alex
   
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 

Author Comment

by:RySk8er30
ID: 10870250
Hi,

I have sent my code.  Thanks.

Ryan
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10870900
Ok, it runs. That are my changes:


1. void TransDatabase::displayTransLog

      //This will loop through the array, printing out each item until it has reached the max number
      for (int n = 0; n < i; n += 5)

Here you had

      for (int n = 0; n = i; n += 5) // n = i is true for any n != 0

2. void TransDatabase::loadTransactionLog

      transRecordsSize = i;

Here you had

      // transRecordsSize = i;    


3. static int menuChoice

            switch (temp) {

                //Valid input
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                    choice = temp - '0'; //Sets choice to inputted value
                    exit = true;
                    break;
                //Invalid input
                default:
                    MessageBeep(0xFFFFFFFF);
            }
       
You had

            switch (temp) {

                //Valid input
                case toascii(49):
                case toascii(50):
                case toascii(51):
                case toascii(52):
                case toascii(53):
                    choice = toascii(temp) - 48; //Sets choice to inputted value
                    exit = true;
                    break;
                //Invalid input
                default:
                    MessageBeep(0xFFFFFFFF);
            }

- The '6' == ascii 54 was missing.
- toascii does nothing as temp is already ascii (0 ... 127)
- Use characters and not ascii values for simplicity


Still to do:

- the exit function didn't work as there is no break in the main loop().
- add error handling when reading files

Regards, Alex
         
0
 

Author Comment

by:RySk8er30
ID: 10871056
Hi,

Thanks for the help, but the program still doesn't load the info from the file.  As far as your "still to do".  I don't want the exit function to exit the program, and I willa dd error handling to the reading of files.

When I run the program all I get is "press any key to continue", then the program closes.

Ryan
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10871157
But it works !!

If i enter 4 i got all transactions from the 1234.txt input file.

You definitively have to make these changes:

1.     for (int n = 0; n < i; n += 5)

Here 'n = i' must be changed to 'n < i' or the output loop shows only one element.

2.     transRecordsSize = i;

That was commented in the source i got from you, but before outputting you set  'i = transRecordsSize;' so you have to store the number of items read to that variable.

Did you see 10 'H' characters when reading the input file?

Regards, Alex




0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10871205
Did you run it in the Debugger? What exit code, error message is shown in the output window?

That time.obj file you sent? Where is it from? Is it Debug or Release object?

Regards, Alex
0
 

Author Comment

by:RySk8er30
ID: 10871452
Hi,

I seem to have a problem with the variable transRecordsSize.  When I try to run this...

transRecordsSize = 0;

in the constructor, the program will not run.  When I comment it out it works.  Then in the loadTransactionLog function, when I run this...

transRecordsSize = i;

I get a problem too.

Ryan
0
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 75 total points
ID: 10871514
That's strange.

Maybe it's because of "Time.h" as there is a system header file that has the same name.

You could try to rename your time.h to timex.h and change include statements. Then, you should choose 'Compile All' to get a proper new status. Try to add another dummy member to your class. Maybe you got alignment problems..

I had to leave now. If you have still problems tomorrow. i'll send you my project files. Maybe they are better...

Regards, Alex
0
 

Author Comment

by:RySk8er30
ID: 10877475
Hi,

I added

TransDatabase transDatabase

to my private data members in my Account.h file, and added

#include "TransDatabase.h"

to my Account.h file, and everything works. I'm not sure why though, because if it was private I shouldn't have to list it.  Oh well, everything works.  Thanks for all your help.

Ryan
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now