The first version of the Rolodex database program, rolodexdb, expands the block I/O version, forming a simple but authentic demonstration of direct file access. It adds an interactive user interface and functions that dynamically manage a one-file database. It continues to rely on the block I/O functions while demonstrating the seek, tell, flush, and clear functions.
The next evolutionary step of the Rolodex solution adopts an object-oriented architecture, benefiting from its encapsulation. Instances of the card class represent database records, one record for each Rolodex card. The rolodex class and its member functions manage card objects in the database file. The application, roldexdb, provides the user interface and manages the database through a rolodex object.
![]() |
|
| File | Description |
|---|---|
| card.h | The card class specification and the functions managing its instances. |
| rolodex.h | The rolodex class specification and member function prototypes. |
| rolodex.cpp | The rolodex member function definitions accessing the database file. |
| rolodexdb.cpp | The application functions that implement the database operations. |
Each file isolates and organizes some basic program functionality. All four files, the complete working program, are available at the bottom of the page. As only the rolodex member functions relate to direct file access, they are the only functions detailed here. The rolodex functions "sit" between the card and rolodexdb classes, called by a rolodexdb function and using the card class members. The text presents relevant features of these classes, providing a context for the following detailed function descriptions.
class card
{
public:
enum { NAME_SZ = 20, // (a)
ADDR_SZ = 40, PHONE_SZ = 15 };
private:
char name[NAME_SZ] = ""; // (b)
char address[ADDR_SZ] = "";
char phone[PHONE_SZ] = "";
public:
card(); // (c)
card(char* n, char* a, char* p); // (d)
char* get_name(); // (e)
bool equals(char* target); // (f)
void print(); // (g)
void print(int record); // (h)
};
public makes them available to the application program.
void rolodexdb::run()
{
rolodex contacts;
char name[card::NAME_SZ];
char address[card::ADDR_SZ];
char phone[card::PHONE_SZ];
while (true)
{
int operation = menu();
switch (operation)
{
case APPEND : // append new card at end
input("Name", name, card::NAME_SZ);
input("Address", address, card::ADDR_SZ);
input("Phone#", phone, card::PHONE_SZ);
contacts.append(name, address, phone);
break;
case SEARCH : // search for a card by name
input("Search name", name, card::NAME_SZ);
contacts.search(name);
break;
case EDIT : // edit a card
input("Search name", name, card::NAME_SZ);
input("New address", address, card::ADDR_SZ);
input("New phone#", phone, card::PHONE_SZ);
contacts.edit(card(name, address, phone));
break;
case REPLACE :
input("New name", name, card::NAME_SZ);
input("New address", address, card::ADDR_SZ);
input("New phone#", phone, card::PHONE_SZ);
contacts.replace(input("Record number"), card(name, address, phone));
break;
case LIST : // list all cards
contacts.list();
break;
case QUIT : // quit
return;
default:
cerr << "Unknown option: " << operation << endl;
break;
}
cout << endl;
}
}
class rolodex
{
private:
fstream data;
streampos find_name(char* name, card& data);
public:
rolodex();
~rolodex() { data.close(); }
void append(char* name, char* address, char* phone);
void search(char* name);
void list();
void edit(card contact);
void replace(int record, card contact);
};
rolodex::rolodex()
{
data.open("rolodex", ios::binary | ios::in | ios::out); // (a)
if (!data.is_open()) // (b)
{
ofstream make("rolodex.bin"); // (c)
make.close(); // (d)
data.open("rolodex.bin", ios::binary | ios::in | ios::out); // (e)
}
if (!data.good()) // (f)
{
cerr << "Unable to open data file." << endl;
exit(1);
}
}
void rolodex::append(char* name, char* address, char* phone)
{
card c(name, address, phone); // (a)
data.seekp(0, ios::end); // (b)
data.write((char *) &c, sizeof(card)); // (c)
data.flush(); // (d)
}
void rolodex::search(char* name)
{
card contact; // (a)
streampos pos = find_name(name, contact); // (b)
if (pos == (streampos)-1) // (c)
cout << name << " not found in the Rolodex\n";
else
contact.print(); // (d)
data.clear(); // (e)
}
void rolodex::list()
{
card contact; // (a)
data.seekg(0); // (b)
while (data.read((char *) &contact, sizeof(card))) // (c)
contact.print(); // (d)
data.clear(); // (e)
}
void rolodex::edit(card a_card)
{
card contact; // (a)
streampos pos = find_name(a_card.get_name(), contact); // (b)
if (pos == (streampos)-1) // (c)
{
cout << a_card.get_name() << " not found in the Rolodex\n";
data.clear();
return;
}
data.seekp(pos); // (d)
data.write((char *) &a_card, sizeof(card)); // (e)
data.flush(); // (f)
}
void rolodex::replace(int record, card contact)
{
if (record < 0) // (a)
{
cout << "Block number must be >= 0\n";
return;
}
card temp; // (b)
data.seekg(record * sizeof(card)); // (c)
data.read((char *) &temp, sizeof(card));
if (!data.good()) // (d)
{
cout << record << " is beyond the file's end" << endl;
data.clear(); // (e)
return;
}
data.seekp(record * sizeof(card)); // (f)
data.write((char *) &contact, sizeof(card));
data.flush();
}
streampos rolodex::find_name(char* name, card& contact)
{
data.seekg(0); // (a)
while (data.read((char *) &contact, sizeof(card))) // (b)
if (contact.equals(name))
return data.tellg() - (streampos)sizeof(card); // (c)
return -1; // (d)
}
| View | Download | Comments |
|---|---|---|
| card.h | card.h | The card class specification and inlined member functions. |
| rolodex.h | rolodex.h | The rolodex class specification. |
| rolodex.cpp | rolodex.cpp | The rolodex member functions as detailed above. These functions constitute the random file access examples. |
| rolodexdb.cpp | rolodexdb.cpp | A simplified database example providing a context for random file access. |