Tom's Guide | Tom's Hardware | Tom's Games
![]() |
![]() |
![]() |
I have an interesting problem.
I have a very simple database program that I am writing for a class project. The database is supposed to hold 3 types of values(records), each with a certain set of fields. So far I have everything working and am able to save the database, normally stored in memory, to a file. The problem is that I cannot read the database from the same file and place it back into memory.
The database is ordered as follows:
struct DBType //declaring data structure(global)
{
char Type; // Type of record
char FName[31]; // First name
char LName[31]; // Last name
char BName[31]; // Business name
double Rate; // Rate
}There are three possible types:
Type 1 is employee and uses the FName, LName, and Rate fields.
Type 2 is business and uses the BName and Rate fields.
Type 3 is a monthly budget and uses the Rate field.I am currently storing the database as a tab deliminated file with a tab between each field and each record on its own line.
Here is the code that I am using to save the file:
void Disk::savedbase()
{
string filename = "gov.dat";
ofstream outFile;outFile.open(filename.c_str());
if (outFile.fail())
{
cout << "\nThe file was not successfully opened" << endl;
return;
}outFile << setiosflags(ios::fixed)
<< setiosflags(ios::showpoint)
<< setprecision(2);for(unsigned int i=0; i < DataBase.size(); i++)
{
DBTemp = DataBase[i];
if (DBTemp.Type == 1)
{
outFile << "1" << "\t";
outFile << DBTemp.FName << "\t";
outFile << DBTemp.LName << "\t";
outFile << DBTemp.Rate << endl;
}
else if (DBTemp.Type == 2)
{
outFile << "2" << "\t";
outFile << DBTemp.BName << "\t";
outFile << DBTemp.Rate << endl;
}
else if (DBTemp.Type == 3)
{
outFile << "3" << "\t";
outFile << DBTemp.Rate << endl;
}
}
outFile.close();cout << "\nThe database has been successfully written." << endl;
cout << "\nPress Enter to continue." << endl;
cin.get();
}Yes it does work just fine and produces a file such as this one:
1 Firstname Lastname 4000
2 Business Name 4000
3 50000
1 Firstname1 Lastname1 300The fields are dependent on the type of record, designated by the number in the first column, and are saved in the file in the order that they are entered in the program.
What I need to do is retrieve the records from the file and place them back into the database. This needs to be done by the type of record as each one has a different number of fields and to make it easier to place it back into the database.
The database is stored in RAM so each time the program restarts it is cleared out. In other words there is no reason to worry about overwriting or appending an existing database.
Thanks in advanced for any help.

A fairly well thought out post, even if it was just copied/pasted from the assignment.
DISCLAIMER: It's 10:45 right now. I woke up around 8:30... yesterday. Simple bugs may be present, but it does compile under VC++. Same goes for gramr and spelng.
I modified your struct a bit. It makes output and file dumping easy:
struct DBType { //declaring data structure(global)
friend std::ostream& operator<<(std::ostream& o, const DBType& d) {
char type = (d.Type >= '0') ? d.Type : d.Type + '0';
//'0' == 48, BTW.
o.setf(std::ios::fixed | std::ios::showpoint); //Feel free to
o.precision(2); //replace these 2 lines w/ stuff from iomanip
o << type << '\t';
switch (type) {
case '1':
o << d.FName << '\t' << d.LName
<< '\t' << d.Rate << '\n';
break;
case '2':
o << d.BName << '\t';
case '3':
o << d.Rate << '\n';
}
return o;
}
char Type; // Type of record
char FName[31]; // First name
union {
char LName[31]; // Last name
char BName[31]; // Business name
};
double Rate; // Rate
};
Seeing as how you already have the output function, input should be pretty easy for you. Still, if you have a specific question, fire away. I suggest you use getline(). You'll also need ignore() (probably). Your biggest design issue is how you plan on getting the data into the struct. Do you make an empty struct, then make a friend std::istream& operator>>(std::istream& i, DBType& d) function, or do you just manually punch in the values? Also, how are you going to keep track of your structs? Array? Homemade linked list? std::list<DBType>?

Specific question away.
What I need is some help in how to parse the file so that I can place it into the different functions. My first thought is to take the first field and based on that take the other fields one at a time and place them into their proper container before dumping it all back into the database in memory.
Lets say that the first field is a 1. Based on this I know that the rest of the record contains the FName, LName, and Rate fields in that order for an employee. What I need then is some way to take one at a time and place it into its respective container then dump it to the database. Here is how this is done in the initial entry of an employee:
cout << "\nPlease hit the enter key after each entry." << endl;
cout << "Please enter an employee name(Last,First) then Rate:\n" << endl;
cin.getline (DBTemp.LName,30);
cin.getline (DBTemp.FName,30);
cin >> DBTemp.Rate;
DBTemp.Type = 1;
cin.ignore();
DataBase.push_back(DBTemp);
Yes I know that there are some issues with this code, such as a complete lack of data validation, but it does work. I was thinking of using something similar when parsing the file, say grabbing a field into a temporary array and then dumping it to the proper DBTemp container.
So to reiterate, how do I get the fields out of the record into the array when there are multiple tabs in each record and a different number of tabs in each type of record.edit: Side question. How did you get that blue text?

The nice thing about ifstream is that it inherits from the same base object as cin. As a consequence, a lot of the functions are identical. In this case, I'd pull the first field, the type, then use that to fill in the other fields.
HOW do you go about filling the values? Well, operator>> works, as does another incarnation of getline(char &buff, int size, char delim). getline() will grab everything until it reaches the specified size, or it hits the delim. Obviously, your delimiter will be '\t'. Between those two functions and ignore(), you should have everything you need. So, only one quick example to get you started:
std::ifstream inf("input.txt");
DBType DBTemp;
while (inf >> DBTemp.Type) {
inf.ignore(); //Gets rid of the '\t' after the type
DBTemp.Type -= '0'; //Makes the var a number, not a character.
switch (DBTemp.Type) {
case 1:
inf.getline(DBTemp.FName, 31, '\t');. . . . . . . . . . . . . . .
Side question. How did you get that blue text?
With the magic of HTML, baby!Seriously, the <font> tag works here, as does the <pre> tag.

![]() |
Delete a folder when it h...
|
Grand Total of variables ...
|

This post is quite old and has been locked from receiving new replies. Please create a new posting instead.
| Ads by Google |