File Processing: 2008 Pearson Education, Inc. All Rights Reserved
File Processing: 2008 Pearson Education, Inc. All Rights Reserved
11
File Processing
2008 Pearson Education, Inc. All rights reserved.
OBJECTIVES
In this chapter youll learn: To create, read, write and update files. Sequential file processing. Random-access file processing. To use high-performance unformatted I/O operations. The differences between formatted-data and raw-data file processing. To build a transaction-processing program using random-access file processing.
2008 Pearson Education, Inc. All rights reserved.
17.1 17.2 17.3 17.4 17.5 17.6 17.7 17.8 17.9 17.10 17.11
Introduction The Data Hierarchy Files and Streams Creating a Sequential File Reading Data from a Sequential File Updating Sequential Files Random-Access Files Creating a Random-Access File Writing Data Randomly to a Random-Access File Reading from a Random-Access File Sequentially Case Study: A Transaction-Processing Program
17.1 Introduction
Files
Used for data persistence
Permanent retention of large amounts of data
10
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
// Fig. 17.4: Fig17_04.cpp // Create a sequential file. #include <iostream> using using using using using std::cerr; std::cin; std::cout; std::endl; std::ios;
11
Outline
Fig17_04.cpp
(1 of 2)
#include <fstream> // file stream using std::ofstream; // output file stream #include <cstdlib> using std::exit; // exit function prototype
Overloaded operator! will return true if the file did not open successfully
30 31 32 33 34 35 36 37 38 39 40 41 42 return 0; // ofstream destructor closes file 43 } // end main Enter Enter ? 100 ? 200 ? 300 ? 400 ? 500 ? ^Z the account, name, and balance. end-of-file to end input. Jones 24.98 Doe 345.67 White 0.00 Stone -42.16 Rich 224.62 // read account, name and balance from cin, then place in file while ( cin >> account >> name >> balance ) { cout << "? "; } // end while int account; char name[ 30 ]; double balance;
12
Outline
Overloaded operator void * will return the null pointer 0 Fig17_04.cpp (false) when the user enters the end-of-file indicator (2 of 2) Write data to client.dat using the stream insertion operator ofstream destructor implicitly closes the file
outClientFile << account << ' ' << name << ' ' << balance << endl;
13
14
Mode
ios::app ios::ate ios::in ios::out ios::trunc ios::binary
Description
Append all output to the end of the file. Open a file for output and move to the end of the file (normally used to append data to a file). Data can be written anywhere in the file. Open a file for input. Open a file for output. Discard the files contents if they exist (this also is the default action for ios::out). Open a file for binary (i.e., nontext) input or output.
15
16
Computer system
UNIX/Linux/Mac OS X Microsoft Windows VAX (VMS)
Keyboard combination
<ctrl-d> (on a line by itself) <ctrl-z> (sometimes followed by pressing Enter) <ctrl-z>
Fig. 17.6 | End-of-file key combinations for various popular computer systems.
17
18
19
20
21
22
1 2 3 4 5 6 7 8 9
// Fig. 17.7: Fig17_07.cpp // Reading and printing a sequential file. #include <iostream> using std::cerr; using std::cout; using std::endl; using std::fixed; using std::ios; using std::left;
23
Outline
Fig17_07.cpp
(1 of 3)
10 using std::right; 11 using std::showpoint; 12 13 #include <fstream> // file stream 14 using std::ifstream; // input file stream 15 16 #include <iomanip> 17 using std::setw; 18 using std::setprecision; 19 20 #include <string> 21 using std::string; 22 23 #include <cstdlib> 24 using std::exit; // exit function prototype 25 26 void outputLine( int, const string, double ); // prototype
27 28 int main() 29 { 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 cout << left << setw( 10 ) << "Account" << setw( 13 ) << "Name" << "Balance" << endl << fixed << showpoint; // display each record in file while ( inClientFile >> account >> name >> balance ) outputLine( account, name, balance ); // ifstream constructor opens the file ifstream inClientFile( "clients.dat", ios::in ); // exit program if ifstream could not open file if ( !inClientFile ) { cerr << "File could not be opened" << endl; exit( 1 ); } // end if int account; char name[ 30 ]; double balance;
24
Outline
Open clients.dat for input
Fig17_07.cpp
Overloaded operator void * returns a null pointer 0 (false) when the end of clients.dat is reached
53 54 // display single record from file 55 void outputLine( int account, const string name, double balance ) 56 { 57 58 cout << left << setw( 10 ) << account << setw( 13 ) << name << setw( 7 ) << setprecision( 2 ) << right << balance << endl;
25
Outline
Fig17_07.cpp
59 } // end function outputLine Account 100 200 300 400 500 Name Jones Doe White Stone Rich Balance 24.98 345.67 0.00 -42.16 224.62
(3 of 3)
1 2 3 4 5 6 7 8 9 10
// Fig. 17.8: Fig17_08.cpp // Credit inquiry program. #include <iostream> using std::cerr; using std::cin; using using using using using std::cout; std::endl; std::fixed; std::ios; std::left;
26
Outline
Fig17_08.cpp
(1 of 6)
11 using std::right; 12 using std::showpoint; 13 14 #include <fstream> 15 using std::ifstream; 16 17 #include <iomanip> 18 using std::setw; 19 using std::setprecision; 20 21 #include <string> 22 using std::string; 23 24 #include <cstdlib> 25 using std::exit; // exit function prototype 26 27 enum RequestType { ZERO_BALANCE = 1, CREDIT_BALANCE, DEBIT_BALANCE, END }; 28 int getRequest(); 29 bool shouldDisplay( int, double ); 30 void outputLine( int, const string, double );
31 32 int main() 33 { 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 // ifstream constructor opens the file ifstream inClientFile( "clients.dat", ios::in ); // exit program if ifstream could not open file if ( !inClientFile ) { cerr << "File could not be opened" << endl; exit( 1 ); } // end if int request; int account; char name[ 30 ]; double balance; // get user's request (e.g., zero, credit or debit balance) request = getRequest();
27
Outline
Fig17_08.cpp
(2 of 6)
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
// process user's request while ( request != END ) { switch ( request ) { case ZERO_BALANCE: cout << "\nAccounts with zero balances:\n"; break; case CREDIT_BALANCE: cout << "\nAccounts with credit balances:\n"; break; case DEBIT_BALANCE: cout << "\nAccounts with debit balances:\n"; break; } // end switch // read account, name and balance from file inClientFile >> account >> name >> balance; // display file contents (until eof) while ( !inClientFile.eof() ) { // display record if ( shouldDisplay( request, balance ) ) outputLine( account, name, balance ); // read account, name and balance from file inClientFile >> account >> name >> balance; } // end inner while
28
Outline
Fig17_08.cpp
(3 of 6)
82 83 84 85 86
inClientFile.clear(); // reset eof for next input inClientFile.seekg( 0 ); // reposition to beginning of file request = getRequest(); // get additional request from user } // end outer while
29
Outline
87 cout << "End of run." << endl; 88 return 0; // ifstream destructor closes the file 89 } // end main 90 91 // obtain request from user 92 int getRequest() 93 { 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 do // input user request { cout << "\n? "; cin >> request; } while ( request < ZERO_BALANCE && request > END ); return request; int request; // request from user // display request options cout << "\nEnter request" << endl << << << << " " " " 1 2 3 4 -
Use ostream member function seekg to reposition the fileFig17_08.cpp position pointer to the beginning (4 of 6)
List accounts with zero balances" << endl List accounts with credit balances" << endl List accounts with debit balances" << endl End of run" << fixed << showpoint;
112 // determine whether to display given record 113 bool shouldDisplay( int type, double balance ) 114 { 115 116 117 118 119 120 121 122 123 124 125 126 127 129 130 // display single record from file 131 void outputLine( int account, const string name, double balance ) 132 { 133 134 cout << left << setw( 10 ) << account << setw( 13 ) << name << setw( 7 ) << setprecision( 2 ) << right << balance << endl; return false; 128 } // end function shouldDisplay // determine whether to display debit balances if ( type == DEBIT_BALANCE && balance > 0 ) return true; // determine whether to display credit balances if ( type == CREDIT_BALANCE && balance < 0 ) return true; // determine whether to display zero balances if ( type == ZERO_BALANCE && balance == 0 ) return true;
30
Outline
Fig17_08.cpp
(5 of 6)
Enter request 1 - List accounts with zero balances 2 - List accounts with credit balances 3 - List accounts with debit balances 4 - End of run ? 1 Accounts with zero balances: 300 White 0.00 Enter request 1 - List accounts with zero balances 2 - List accounts with credit balances 3 - List accounts with debit balances 4 - End of run ? 2 Accounts with credit balances: 400 Stone -42.16 Enter request 1 - List accounts with zero balances 2 - List accounts with credit balances 3 - List accounts with debit balances 4 - End of run ? 3 Accounts with debit balances: 100 Jones 24.98 200 Doe 345.67 500 Rich 224.62 Enter request 1 - List accounts with zero balances 2 - List accounts with credit balances 3 - List accounts with debit balances 4 - End of run ? 4 End of run.
31
Outline
Fig17_08.cpp
(6 of 6)
32
33
34
35
First argument
A const char * pointing to bytes in memory
Second argument
A size_t specifying the number of bytes to write
Example
outFile.write( reinterpret_cast<const char *>( &number ), sizeof( number ) );
2008 Pearson Education, Inc. All rights reserved.
36
37
38
39
1 2 3 4 5 6 7 8 9
// Fig. 17.10: ClientData.h // Class ClientData definition used in Fig. 17.12Fig. 17.15. #ifndef CLIENTDATA_H #define CLIENTDATA_H #include <string> using std::string;
40
Outline
ClientData.h
(1 of 2)
class ClientData
10 { 11 public: 12 13 14 15 16 17 18 19 20 21 22 23 24 25 // accessor functions for firstName void setFirstName( string ); string getFirstName() const; // accessor functions for lastName void setLastName( string ); string getLastName() const; // accessor functions for accountNumber void setAccountNumber( int ); int getAccountNumber() const; // default ClientData constructor ClientData( int = 0, string = "", string = "", double = 0.0 );
26 27 28 29 31 32 33 34 36 37 #endif // accessor functions for balance void setBalance( double ); double getBalance() const; int accountNumber; char lastName[ 15 ]; char firstName[ 10 ]; double balance;
41
Outline
30 private:
ClientData.h
(2 of 2)
Store the first and last name in fixed-length char arrays we cannot use strings because they do not have uniform length
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
// Fig. 17.11: ClientData.cpp // Class ClientData stores customer's credit information. #include <string> using std::string; #include "ClientData.h" // default ClientData constructor ClientData::ClientData( int accountNumberValue, string lastNameValue, string firstNameValue, double balanceValue ) { setAccountNumber( accountNumberValue ); setLastName( lastNameValue ); setFirstName( firstNameValue ); setBalance( balanceValue ); } // end ClientData constructor // get account-number value int ClientData::getAccountNumber() const { return accountNumber;
42
Outline
ClientData.cpp
(1 of 3)
22 } // end function getAccountNumber 23 24 // set account-number value 25 void ClientData::setAccountNumber( int accountNumberValue ) 26 { 27 accountNumber = accountNumberValue; // should validate 28 } // end function setAccountNumber
29 30 // get last-name value 31 string ClientData::getLastName() const 32 { 33 35 36 // set last-name value 37 void ClientData::setLastName( string lastNameString ) 38 { 39 40 41 42 43 44 46 47 // get first-name value 48 string ClientData::getFirstName() const 49 { 50 return firstName; 51 } // end function getFirstName // copy at most 15 characters from string to lastName const char *lastNameValue = lastNameString.data(); int length = lastNameString.size(); length = ( length < 15 ? length : 14 ); strncpy( lastName, lastNameValue, length ); lastName[ length ] = '\0'; // append null character to lastName return lastName; 34 } // end function getLastName
43
Outline
ClientData.cpp
(2 of 3)
string member function data returns an array containing the characters of the string (not guaranteed to be null terminated) string member function size returns the length of lastNameString
52 53 // set first-name value 54 void ClientData::setFirstName( string firstNameString ) 55 { 56 57 58 59 60 61 63 64 // get balance value 65 double ClientData::getBalance() const 66 { 67 69 70 // set balance value 71 void ClientData::setBalance( double balanceValue ) 72 { 73 balance = balanceValue; 74 } // end function setBalance return balance; 68 } // end function getBalance // copy at most 10 characters from string to firstName const char *firstNameValue = firstNameString.data(); int length = firstNameString.size(); length = ( length < 10 ? length : 9 ); strncpy( firstName, firstNameValue, length ); firstName[ length ] = '\0'; // append null character to firstName
44
Outline
ClientData.cpp
(3 of 3)
1 2 3 4 5 6 7 8 9 10
// Fig. 17.12: Fig17_12.cpp // Creating a randomly accessed file. #include <iostream> using std::cerr; using std::endl; using std::ios; #include <fstream> using std::ofstream;
45
Outline
Fig17_12.cpp
(1 of 2)
11 #include <cstdlib> 12 using std::exit; // exit function prototype 13 14 #include "ClientData.h" // ClientData class definition 15
16 int main() 17 { 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 return 0; 35 } // end main // output 100 blank records to file for ( int i = 0; i < 100; i++ ) outCredit.write( reinterpret_cast< const char * >( &blankClient ), sizeof( ClientData ) ); ClientData blankClient; // constructor zeros out each data member // exit program if ofstream could not open file if ( !outCredit ) { cerr << "File could not be opened." << endl; exit( 1 ); } // end if ofstream outCredit( "credit.dat", ios::out | ios::binary );
46
Outline
Open credit.dat in binary mode, which is required to Fig17_12.cpp write fixed-length records
(2 of 2)
47
Separate each open mode from the next with the bitwise inclusive OR operator (|)
Use function seekp to set the put file-position pointer to the specific position
Example calculation ( n 1 ) * sizeof( ClientData ) Byte location for nth ClientData record
1 2 3 4 5 6 7 8
// Fig. 17.13: Fig17_13.cpp // Writing to a random-access file. #include <iostream> using std::cerr; using std::cin; using std::cout; using std::endl; using std::ios;
48
Outline
Fig17_13.cpp
9 10 #include <iomanip> 11 using std::setw; 12 13 #include <fstream> 14 using std::fstream; 15 16 #include <cstdlib> 17 using std::exit; // exit function prototype 18 19 #include "ClientData.h" // ClientData class definition 20 21 int main() 22 { 23 int accountNumber; 24 char lastName[ 15 ]; 25 26 27 28 29 char firstName[ 10 ]; double balance;
(1 of 4)
Create fstream outCredit to open credit.dat for input and output in binary mode
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
// exit program if fstream cannot open file if ( !outCredit ) { cerr << "File could not be opened." << endl; exit( 1 ); } // end if cout << "Enter account number (1 to 100, 0 to end input)\n? "; // require user to specify account number ClientData client; cin >> accountNumber; // user enters information, which is copied into file while ( accountNumber > 0 && accountNumber <= 100 ) { // user enters last name, first name and balance cout << "Enter lastname, firstname, balance\n? "; cin >> setw( 15 ) >> lastName; cin >> setw( 10 ) >> firstName; cin >> balance; // set record accountNumber, lastName, firstName and balance values client.setAccountNumber( accountNumber ); client.setLastName( lastName ); client.setFirstName( firstName ); client.setBalance( balance );
49
Outline
Fig17_13.cpp
(2 of 4)
58 59 60 61 62 63 64 65 66 67 68 69 70 71
// seek position in file of user-specified record outCredit.seekp( ( client.getAccountNumber() - 1 ) * sizeof( ClientData ) ); // write user-specified information in file outCredit.write( reinterpret_cast< const char * >( &client ), sizeof( ClientData ) );
50
Outline
(3 of 4)
// enable user to enter another account cout << "Enter account number\n? "; cin >> accountNumber; } // end while return 0;
72 } // end main
Enter account number (1 to 100, 0 to end input) ? 37 Enter lastname, firstname, balance ? Barker Doug 0.00 Enter account number ? 29 Enter lastname, firstname, balance ? Brown Nancy -24.54 Enter account number ? 96 Enter lastname, firstname, balance ? Stone Sam 34.98 Enter account number ? 88 Enter lastname, firstname, balance ? Smith Dave 258.34 Enter account number ? 33 Enter lastname, firstname, balance ? Dunn Stacey 314.33 Enter account number ? 0
51
Outline
Fig17_13.cpp
(4 of 4)
52
Additional benefit
Sequentially read-in records are sorted in order of ascending record keys Space-time trade off: a fast sorting algorithm, but spaceconsuming
2008 Pearson Education, Inc. All rights reserved.
1 2 3 4 5 6 7 8
// Fig. 17.14: Fig17_14.cpp // Reading a random access file sequentially. #include <iostream> using std::cerr; using std::cout; using std::endl; using std::fixed; using std::ios;
53
Outline
Fig17_14.cpp
9 using std::left; 10 using std::right; 11 using std::showpoint; 12 13 #include <iomanip> 14 using std::setprecision; 15 using std::setw; 16 17 #include <fstream> 18 using std::ifstream; 19 using std::ostream; 20 21 #include <cstdlib> 22 using std::exit; // exit function prototype 23 24 #include "ClientData.h" // ClientData class definition 25 26 void outputLine( ostream&, const ClientData & ); // prototype 27
(1 of 3)
28 int main() 29 { 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 // read first record from file inCredit.read( reinterpret_cast< char * >( &client ), sizeof( ClientData ) ); // read all records from file while ( inCredit && !inCredit.eof() ) { // display record if ( client.getAccountNumber() != 0 ) outputLine( cout, client ); ifstream inCredit( "credit.dat", ios::in | ios::binary ); // exit program if ifstream cannot open file if ( !inCredit ) { cerr << "File could not be opened." << endl; exit( 1 ); } // end if cout << left << setw( 10 ) << "Account" << setw( 16 ) << "Last Name" << setw( 11 ) << "First Name" << left << setw( 10 ) << right << "Balance" << endl; ClientData client; // create record
54
Outline
Fig17_14.cpp
(2 of 3)
This loop-continuation condition evaluates to false if an error occurs when reading from the file or if the end of file is reached
56 57 58 59 60 61 63
// read next from file inCredit.read( reinterpret_cast< char * >( &client ), sizeof( ClientData ) ); } // end while return 0;
55
Outline
Because outputLine takes an ostream reference as argument, it can be used with cout (an Fig17_14.cpp ostream object) or an ofstream object (derived from ostream) to output to the screen or to a file (3 of 3)
65 void outputLine( ostream &output, const ClientData &record ) 66 { 67 68 69 70 71 output << left << setw( 10 ) << record.getAccountNumber() << setw( 16 ) << record.getLastName() << setw( 11 ) << record.getFirstName() << setw( 10 ) << setprecision( 2 ) << right << fixed << showpoint << record.getBalance() << endl;
72 } // end function outputLine Account 29 33 37 88 96 Last Name Brown Dunn Barker Smith Stone First Name Nancy Stacey Doug Dave Sam Balance -24.54 314.33 0.00 258.34 34.98
56
1 2 3 4 5 6 7 8
// Fig. 17.15: Fig17_15.cpp // This program reads a random access file sequentially, updates // data previously written to the file, creates data to be placed // in the file, and deletes data previously in the file. #include <iostream> using std::cerr; using std::cin; using std::cout;
57
Outline
Fig17_15.cpp
9 using std::endl; 10 using std::fixed; 11 using std::ios; 12 13 14 15 16 17 using std::left; using std::right; using std::showpoint; #include <fstream> using std::ofstream;
(1 of 10)
18 using std::ostream; 19 using std::fstream; 20 21 #include <iomanip> 22 using std::setw; 23 using std::setprecision; 24 25 #include <cstdlib> 26 using std::exit; // exit function prototype 27 28 #include "ClientData.h" // ClientData class definition 29
30 int enterChoice(); 31 void createTextFile( fstream& ); 32 void updateRecord( fstream& ); 33 void newRecord( fstream& ); 34 void deleteRecord( fstream& ); 35 void outputLine( ostream&, const ClientData & ); 36 int getAccount( const char * const ); 37 38 enum Choices { PRINT = 1, UPDATE, NEW, DELETE, END }; 39 40 int main() 41 { 42 43 44 45 46 47 48 49 50 51 52 53 int choice; // store user choice // exit program if fstream cannot open file if ( !inOutCredit ) { cerr << "File could not be opened." << endl; exit ( 1 ); } // end if // open file for reading and writing fstream inOutCredit( "credit.dat", ios::in | ios::out | ios::binary );
58
Outline
Fig17_15.cpp
(2 of 10)
Or together modes ios::in and ios::out for both reading and writing capabilities
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
// enable user to specify action while ( ( choice = enterChoice() ) != END ) { switch ( choice ) { case PRINT: // create text file from record file createTextFile( inOutCredit ); break; case UPDATE: // update record updateRecord( inOutCredit ); break; case NEW: // create record newRecord( inOutCredit ); break; case DELETE: // delete existing record deleteRecord( inOutCredit ); break; default: // display error if user does not select valid choice cerr << "Incorrect choice" << endl; break; } // end switch inOutCredit.clear(); // reset end-of-file indicator } // end while
59
Outline
Fig17_15.cpp
(3 of 10)
82 // enable user to input menu choice 83 int enterChoice() 84 { 85 86 87 88 89 90 91 92 93 94 95 96 int menuChoice; cin >> menuChoice; // input menu selection from user return menuChoice; // display available options cout << "\nEnter your choice" << endl << "1 - store a formatted text file of accounts" << endl << " called \"print.txt\" for printing" << endl << "2 - update an account" << endl << "3 - add a new account" << endl << "4 - delete an account" << endl << "5 - end program\n? ";
60
Outline
Fig17_15.cpp
(4 of 10)
97 } // end function enterChoice 98 99 // create formatted text file for printing 100 void createTextFile( fstream &readFromFile ) 101 { 102 // create text file 103 ofstream outPrintFile( "print.txt", ios::out ); 104 105 106 107 108 109 110 111 // exit program if ofstream cannot create file if ( !outPrintFile ) { cerr << "File could not be created." << endl; exit( 1 ); } // end if
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
outPrintFile << left << setw( 10 ) << "Account" << setw( 16 ) << "Last Name" << setw( 11 ) << "First Name" << right << setw( 10 ) << "Balance" << endl; // set file-position pointer to beginning of readFromFile readFromFile.seekg( 0 );
61
Outline
// read first record from record file ClientData client; readFromFile.read( reinterpret_cast< char * >( &client ), sizeof( ClientData ) ); // copy all records from record file into text file while ( !readFromFile.eof() ) { // write single record to text file
Use istream member function seekg Fig17_15.cpp to ensure that the file-position pointer is at the beginning of the file (5 of 10)
if ( client.getAccountNumber() != 0 ) // skip empty records outputLine( outPrintFile, client ); // read next record from record file readFromFile.read( reinterpret_cast< char * >( &client ), sizeof( ClientData ) ); } // end while
135 } // end function createTextFile 136 137 // update balance in record 138 void updateRecord( fstream &updateFile ) 139 { 140 141 // obtain number of account to update int accountNumber = getAccount( "Enter account to update" );
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 // move file-position pointer to correct record in file updateFile.seekg( ( accountNumber - 1 ) * sizeof( ClientData ) ); // read first record from file ClientData client; updateFile.read( reinterpret_cast< char * >( &client ), sizeof( ClientData ) ); // update record if ( client.getAccountNumber() != 0 ) { outputLine( cout, client ); // display the record // request user to specify transaction cout << "\nEnter charge (+) or payment (-): "; double transaction; // charge or payment cin >> transaction; // update record balance double oldBalance = client.getBalance(); client.setBalance( oldBalance + transaction ); outputLine( cout, client ); // display the record // move file-position pointer to correct record in file updateFile.seekp( ( accountNumber - 1 ) * sizeof( ClientData ) );
62
Outline
Fig17_15.cpp
(6 of 10) Read data into object client, using istream member function read Determine whether the record contains information Use function outputLine with the cout ostream object to display the record
// write updated record over old record in file updateFile.write( reinterpret_cast< const char * >( &client ), sizeof( ClientData ) ); } // end if else // display error if account does not exist
63
Outline
174 cerr << "Account #" << accountNumber 175 << " has no information." << endl; 176 } // end function updateRecord 177 178 // create and insert record 179 void newRecord( fstream &insertInFile ) 180 { 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 // obtain number of account to create int accountNumber = getAccount( "Enter new account number" ); // move file-position pointer to correct record in file insertInFile.seekg( ( accountNumber - 1 ) * sizeof( ClientData ) ); // read record from file ClientData client; insertInFile.read( reinterpret_cast< char * >( &client ), sizeof( ClientData ) ); // create record, if record does not previously exist if ( client.getAccountNumber() == 0 ) { char lastName[ 15 ]; char firstName[ 10 ]; double balance;
Fig17_15.cpp
(7 of 10)
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
// user enters last name, first name and balance cout << "Enter lastname, firstname, balance\n? "; cin >> setw( 15 ) >> lastName; cin >> setw( 10 ) >> firstName; cin >> balance; // use values to populate account values client.setLastName( lastName ); client.setFirstName( firstName ); client.setBalance( balance ); client.setAccountNumber( accountNumber ); // move file-position pointer to correct record in file insertInFile.seekp( ( accountNumber - 1 ) * sizeof( ClientData ) ); // insert record in file insertInFile.write( reinterpret_cast< const char * >( &client ), sizeof( ClientData ) ); } // end if else // display error if account already exists cerr << "Account #" << accountNumber
64
Outline
Fig17_15.cpp
(8 of 10)
220 << " already contains information." << endl; 221 } // end function newRecord 222 223 // delete an existing record 224 void deleteRecord( fstream &deleteFromFile ) 225 { 226 // obtain number of account to delete 227 228
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 256
// move file-position pointer to correct record in file deleteFromFile.seekg( ( accountNumber - 1 ) * sizeof( ClientData ) ); // read record from file ClientData client; deleteFromFile.read( reinterpret_cast< char * >( &client ), sizeof( ClientData ) ); // delete record, if record exists in file if ( client.getAccountNumber() != 0 ) { ClientData blankClient; // create blank record // move file-position pointer to correct record in file deleteFromFile.seekp( ( accountNumber - 1 ) * sizeof( ClientData ) ); // replace existing record with blank record deleteFromFile.write( reinterpret_cast< const char * >( &blankClient ), sizeof( ClientData ) ); cout << "Account #" << accountNumber << " deleted.\n"; } // end if else // display error if record does not exist cerr << "Account #" << accountNumber << " is empty.\n";
65
Outline
Fig17_15.cpp
(9 of 10)
257 // display single record 258 void outputLine( ostream &output, const ClientData &record ) 259 { 260 261 262 output << left << setw( 10 ) << record.getAccountNumber() << setw( 16 ) << record.getLastName() << setw( 11 ) << record.getFirstName()
66
Outline
263 << setw( 10 ) << setprecision( 2 ) << right << fixed 264 << showpoint << record.getBalance() << endl; 265 } // end function outputLine 266 267 // obtain account-number value from user 268 int getAccount( const char * const prompt ) 269 { 270 int accountNumber; 271 272 273 274 275 276 277 278 279 // obtain account-number value do { cout << prompt << " (1 - 100): "; cin >> accountNumber; } while ( accountNumber < 1 || accountNumber > 100 ); return accountNumber;
Fig17_15.cpp
(10 of 10)