⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 14章 文件处理.txt

📁 C++大学教程txt版中文版 C++大学教程txt版中文版
💻 TXT
📖 第 1 页 / 共 5 页
字号:
 图14.14 的程序顺序读取"credit.dat"文件中的每个记录,检查每个记录中是否包含数据,并打印包含数据的记录。第30行的下列条件:
    while(inCredit && !inCredit.eof(){
用ios成员函数eof确定是否到达文件末尾,如果到达文件末尾,则终止执行while结构。如果读取文件时发生错误,则循环终止,因为inCredit值为false。从文件中输入的数据用outputLine输出,outputLine取两个参数,即ostream对象和要输出的clientData结构。osttream参数类型可以支持任何ostream对象(如cont)或ostream的任何派生类对象(如ofstream类型的对象)作为参数。这样,同一函数既可输出到标准输出流,也可输出到文件流,而不必编写另一个函数。
    这些程序还有另一好处,输出窗口中的记录已经按账号排序列出,这是用直接访问方法将这些记录存放到文件中的结果。试比较第4章介绍的冒泡排序,用直接访问方法排序显然快多了。这个速度是通过生成足够大的文件来保证完成每个记录而实现的。当然,大多数时候文件存储都是稀松的,因此会浪费存储空间。这是另一个以空间换取时间的例子:加大空间可以得到更快的排序算法。

14.11  实例研究:事务处理程序
    下面介绍一个有实际意义的使用随机访问文件的事务处理程序。该程序维护银行的账目信息。
程序能够更新、添加和删除账号,并且能够把所有当前账号的格式化清单存储在一个用于打印的文本文件中。我们假定已经通过执行图14.11中的程序建立了文件eredit.dat,并用图14.12的程序插入了初始值。
    程序有五个选项(第5个选项终止程序)。选项1调用函数textFile把所有的格式化的账号存储在文本文件print.txt中(以后可能要打印这个文件)。函数textFile取一个fstream对象作为参数,用于从eredit.dat文件输入数据。函数textFile用istream成员函数read和图14.14介绍的顺序文件访问方法从credit.dat输入数据。使用14.10节讨论的函数outputLine将数据输出到print.txt文件。注意textFile用istream成员函数seek保证文件位置指针在文件开头。选择了选项1后,文件accounts.txt中包含如下内容:
Account    Last Name   First Name    Balance
29         Brown       Nancy         -24.54
33         Dunn        Stacey        314.33
37         Barker      Doug            0.00
88         Smith       Dave          258.34
96         Stone       Sam            34.98
    选项2调用函数updateRecord更新账号。该函数只更新已存在的记录,所以函数首先检查用户指定的记录是否为空。用istream成员函数read把记录读到结构client中,然后把成员clientaccountNumber与0比较。如果client.accountNumber为0,说明该条记录中不包含信息,因此打印出说明该记录为空的消息,然后再显示出选项菜单。如果记录中包含信息,函数utxlateR~rd用函数outputLine在屏上显示记录,并输入事务金额、计算新的结算结果以及把记录重写到文件中。选项2的典型输出如下所示.
Enter account to update (1 - 100): 37
37        Barker     Doug           0.00
Enter charge (+) or payment (-): +87.99
    选项3调用函数newRecord把新的账号添加到文件中。如果用户键人了一个已有的账号,函数newReeord显示出说明该账号已存在的消息,并再次显示出选项菜单。函数添加新记录的过程与图14.12中的程序所用的方法相同。选项3的典型输出如下所示:
Enter new account number(1 - 100): 22
Enter lastname, firstname, balance
? Johnston Sarah 247.45
    选项4调用函数deleteRecord删除文件中的一条记录。提示用户输入账号,只能删除已存在的记录,如果该账号的记录为空,函数显示出账号不存在的错误消息。如果存在该账号,通过将空记录(blankClient)复制到文件中重新初始化该记录。删除记录时会显示一个消息。选项4的典型输出如下所示:
Enter account to delete(1 - 100): 29
Account #29 deleted.
打开"credit dat" 文件时,要用ios::和ios::out的或操作生成fstream对象以便读写。
1 // Fig. 14.15: figl4_15.cpp
2 // This program reads a random access file sequentially,
3 // updates data already written to the file, creates new
4 // data to be placed in the file, and deletes data
5 // already in the file.
6 #include <iostream.h>
7 #include <fstream.b>
8 #include <iomanip.h>
9 #include <stdlib.h>
10 #include "clntdata.h"
11
12 int enterChoice();
13 void textFile( fstream& );
14 void updateRecord( fstream& );
15 void newRecord( fstream& );
16 void deleteRecord( fstream& );
17 void outputLine( ostream&, const clientData & );
18 int getAccount( const char * );
19
20 enum Choices { TEXTFILE = 1, UPDATE, NEW, DELETE, END } ;
21
22 int main()
23 {
24   fstream inOutCredit( "credit.dat", ios::in | ios::out );
25
26   if ( !inOutCredit ) {
27     cerr << "File could not be opened." << endl;
28     exit ( 1 );
29   }
3O
31   int choice;
32
33 while ( ( choice = enetrChoice() ) != END){
34
35     switch ( choice ) {
36       case TEXTFILE:
37          textFile( inOutCredit );
38          break;
39       case UPDATE:
40          updateReeord( inOutCredit );
41          break;
42       case NEW:
43          newRecord( inOutCredit );
44          break;
45       case DELETE:
46          deleteRecord( inOutCredit );
47          break;
48       default:
49          cerr << "Incorrect cholce\n";
50          break;
51     }
52
53     inOutCredit.clear();  // resets end-of-file indicator
54     }
55
56   return 0;
57 }
58
59 // Prompt for and input menu choice
60 int enterChoice()
61 {
62     cout << "\nEnter your choice" << endl
63          << "i - store a formatted text file of accounts\n"
64          << "   called \"print.txt\" for printing\n"
65          << "2 - update an account\n"
66          << "3 - add a new account\n"
67          << "4 - delete an account\n"
68          << "5 - end program\n? ";
69
70     int menuChoice;
71     cin >> menuChoice;
72     return menuChoice;
73 }
74
75 // Create formatted text file for printing
76 void textFile( fstream &readFromFile )
77 {
78   ofstream outPrintFile( "print.txt", ios::out );
79
80   if ( !outPrintFile ) {
81     cerr << "File could not be opened." << endl;
82     exit( 1 );
83     }
84
85   outPrintFile << setiosflags( ios::left ) << setw( 10 )
86      << "Account" << setw( 16 ) << "Last Name" << setw( 11 )
87      << "First Name" << resetiosflags( ios::left )
88      << setw( 10 ) << "Balance" << endl;
89   readFromFile.seekg(0);
90
91   clientData client;
92   readFromFile.read( reinterpret_cast<char *>( &client ),
93                                        sizeof( clientData ) );
94
95   while (!readFromFile.eof() ) {
96     if ( client.accountNumber != O )
97        outputLine( outPrintFile, client );
98
99     readFromFile.read( reinterpret_cast<char *>( &client ),
100                     sizeof( clientData ) );
1O1   }
102 }
103
104 // Update an account's balance
105 void updateRecord( fstream &updateFile )
106 {
107   int account = getAccount( "Enter account to update" );
108
109   updateFile.seekg( ( account - I ) * sizeof( clientData ) );
110
111   clientData client;
112   updateFile.read( reinterpret_cast<char *>( &client ),
113                 sizeof( clientData ) );
114
115   if ( client.accountNumber != 0 ) {
116     outputLine( cout, client );
117     cout << "\nEnter charge (+) or payment (-): ";
118
119     float transaction;   // charge or payment
120     cin >> transaction;  // should validate
121     client.balance += transaction;
122     outputLine( cout, client );
123     updateFile.seekp((account-1) * sizeof(clientData));
124     updateFile.write(
125        reinterpret cast<const char *>( &client ),
126        sizeof( clientData ) );
127   }
128    else
129      cerr << "Account #" << account
130           << " has no information." << endl;
131 }
132
133 // Create and insert new record
134 void newRecord( fstream &insertInFile )
135 {
136   int account = getAccount( "Enter new account number" );
137
138   insertInFile.seekg( ( account-1 ) * sizeof( clientData  );
139
14O   clientData client;
141   insertInFile.read( reinterpret cast<char *>( &client ),
142                  sizeof( clientData ) );
143
144    if ( client.accountNumber == 0 ) {
145       cout << "Enter lastname, firstname, balance\n? ";
146       cin >> client.lastName >> client.firstName
147                              >> client.balance;
148       client.accountNumber = account;
149       insertInFile.seekp( ( account - 1) *
150                             sizeof( clientData ) );
151       insertInFile.write(
152                             reinterpret_cast<const char *>( &client ),
153                             sizeof( clientData ) );
154    }
155    else
156       cerr << "Account #" << account 
157            << " already contains information." << endl;
158 }
159
160 // Delete an existing record         
161 void deleteRecord( fstream &deleteFromFile )
162 {
163   int account = getAccount( "Enter account to delete" );
164
165   deleteFromFile.seekg((account-1) * sizeof( clientData ) );
166
167   clientData client;
168   deleteFromFile.read( reinterpret_cast<char *> &client ),
169                    sizeof( clientData ) );
170
171   if ( client.accountNumber != 0 ) {
172     clientData blankClient = { 0, "", "", 0.0 };
173
174     deleteFromFile.seekp( ( account - 1) *
175                       sizeof( clientData ) );
176     deleteFromFile.write(
177        reinterpret cast<const char *>( &blankClient ),
178        sizeof( clientData ) );
179     cout << "Account #" << account << " deleted." << endl;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -