What I need to do i something like this:

ClientData.h

#ifndef CLIENTDATA_H
#define CLIENTDATA_H

#include <string>
using std::string;

class ClientData
{
public:
	ClientData(int = 0, string = "", string = "", double = 0.0);

	void SetAccountNumber(int);
	int GetAccountNumber() const;

	void SetLastName(string);
	string GetLastName() const;

	void SetFirstName (string);
	string GetFirstName() const;

	void SetBalance (double);
	double GetBalance() const;

private:
	int     _accountNumber;
	char    _lastName[15];
	char    _firstName[10];
	double  _balance;
};

#endif

ClientData.cpp

#include <string>
using std::string;

#include "ClientData.h"

ClientData::ClientData(int accountNumberValue, string lastNameValue, string firstNameValue, double balanceValue)
{
	SetAccountNumber(accountNumberValue);
	SetLastName(lastNameValue);
	SetFirstName(firstNameValue);
	SetBalance(balanceValue);
}

int ClientData::GetAccountNumber() const
{
	return _accountNumber;
}

void ClientData::SetAccountNumber(int accountNumberValue)
{
	_accountNumber = accountNumberValue;
}


string ClientData::GetLastName() const
{
	return _lastName;
}

void ClientData::SetLastName(string lastNameString)
{
	// copy at most 15 characters from string to lastName
	const char* lastNameValue = lastNameString.data();

	int length = lastNameString.size();

	length = (length < 15 ? length : 14);

	strncpy_s(_lastName, lastNameValue, length);

	_lastName[length] = '\0';
}

string ClientData::GetFirstName() const
{
	return _firstName;
}

void ClientData::SetFirstName(string firstNameString)
{
	const char* firstNameValue = firstNameString.data();

	int length = firstNameString.size();

	length = (length < 10 ? length : 9);

	strncpy_s(_firstName, firstNameValue, length);

	_firstName[length] = '\0'; // append null character to firstName
}

double ClientData::GetBalance() const
{
	return _balance;
}

void ClientData::SetBalance(double balanceValue)
{
	_balance = balanceValue;
}

main.cpp

#include <iostream>
using std::cout;
using std::cin;
using std::cerr;
using std::ios;
using std::endl;
using std::left;
using std::right;
using std::showpoint;
using std::fixed;

#include <fstream>
using std::fstream;
using std::ostream;
using std::ifstream;

#include <iomanip>
using std::setw;
using std::setprecision;

#include "ClientData.h"

void OutputLine(ostream&, const ClientData& );

int main ()
{
	//-----------------------------------------------------------
	// Reading from a Random-Access File Sequentially
	//-----------------------------------------------------------

	ifstream inCredit("credit.dat", ios::in);

	if (!inCredit)
	{
		cerr << "File could not be opened." << endl;
		exit(1);
	}

	cout << left << setw(10) << "Account" << setw(16) << "Last Name" << setw(11) << "First Name" << left << setw(10) << right << "Balance" << endl;

	ClientData client;

	inCredit.read(reinterpret_cast<char*> (&client), sizeof(ClientData));

	while (inCredit && !inCredit.eof())
	{
		//display record
		if (client.GetAccountNumber() != 0)
			OutputLine(cout, client);

		//read next from file
		inCredit.read(reinterpret_cast<char*> (&client), sizeof(ClientData));
	}


	cin.ignore();
	cin.get();
	return 0;
}

void OutputLine(ostream& output, const ClientData& record)
{
	output << left << setw(10) << record.GetAccountNumber()
		   << setw(16) << record.GetLastName()
		   << setw(11) << record.GetFirstName()
		   << setw(10) << setprecision(2) << right << fixed
		   << showpoint << record.GetBalance() << endl;
}

This program reads records from a "credits.dat" file and prints all the records..

But
What I need to do is search for records and print 1 at a time.
for example i should enter the account number of a record and it should print all the information about that record. Keeping in mind that the archive "credits.dat" has many records...

I've been struggling trying to figure out a way to do this.
Any help would be much appreciated....

Recommended Answers

All 6 Replies

If you want a random-access file where you can go to any record without reading all the intermediate records then the file must be in binary form with fixed-length records. Your class ClientData makes that pretty easy to implement because of its fixed-length data objects.

You have to open the files in binary mode using ios::binary flag ofstream out("filename",ios:binary); then use the ofstream's write() function to write out one record. So lets say you need to rewrite the 10th record

#include <fstream>
using namespace std;
int main()
{
    ClassData obj;
    ofstream out("filename", ios::out | ios::binary);
    // seek to the 10th record
    out.seekp(10 * sizeof(ClassData));
    // write the 10th record
    out.write(&obj, sizeof(ClassData));
}

Similar code as above to read the 10th record (or any record in the file)

Only output the record if client.GetAccountNumber() is the account number entered. Similar to your output while loop.

I didn't make that other program i used it as an example for this one I'm making:

Circle.h

#ifndef CIRCLE_H
#define CIRCLE_H

#include <iostream>
#include <fstream>
using namespace std;

class Circle
{
	friend ostream& operator <<(ostream& output, const Circle& aCircle);
	friend istream& operator >>(istream& input, Circle& aCircle);

public:
	Circle();
	Circle(double radius, int id);
	Circle(const Circle& aCircle);

	void SetCircleRadius(double radius) { _circleRadius = radius; }
	void SetCircleId(int id)   { _circleId = id; }

	double GetCircleRadius() const   { return _circleRadius; }
	int GetCircleId() const { return _circleId; }

	friend void AddNewCircle(fstream&);

	friend void AccessCircle(fstream&);

private:
	double  _circleRadius;
	int     _circleId;
};

#endif

Circle.cpp

#include "Circle.h"

Circle::Circle()
{
	_circleId = 0;
	_circleRadius = 0.0;
}

Circle::Circle(double radius, int id)
{
	_circleId = id;
	_circleRadius = radius;
}

Circle::Circle(const Circle& aCircle)
{
	_circleId = aCircle._circleId;
	_circleRadius = aCircle._circleRadius;
}

ostream& operator <<(ostream& output, const Circle& aCircle)
{
	output << aCircle._circleId << endl;
	output << aCircle._circleRadius << endl;

	return (output);
}

istream& operator >>(istream& input, Circle& aCircle)
{
	int quantity;
	cout << "How many circles do you want to add ";
	input >> quantity;

	for (int i = 0; i < quantity; ++i)
	{
		cout << "\nEnter the ID of Circle #" << (i + 1) << " : ";
		input >> aCircle._circleId;

		cout << "Enter Radius of Circle #" << (i + 1) << " : ";
		input >> aCircle._circleRadius;

		cout << endl;
	}

	return (input);
}

void AddNewCircle(fstream& insertInFile)
{
	Circle aCircle;

	cout << "Enter an Id for the circle: ";
	cin >> aCircle._circleId;

	cout << "\nEnter the circle's radius: ";
	cin >> aCircle._circleRadius;

	insertInFile.open("circle.dat", ios::out | ios::binary);

	insertInFile.write(reinterpret_cast<char*> (&aCircle), sizeof(Circle));
}


void AccessCircle(fstream& extractFromFile)
{
	Circle aCircle;

	cout << "Enter an Id for the circle: ";
	cin >> aCircle._circleId;

	extractFromFile.open("circle.dat", ios::in | ios::binary);

	extractFromFile.read(reinterpret_cast<char*> (&aCircle), sizeof(Circle));

}

main.cpp

#include <iostream>
#include <fstream>
#include <map>
using namespace std;

#include "Circle.h"

int main ()
{
	Circle aCircle;
	fstream file;
	int option;

	file.open("Circle.dat", ios::out|ios::out|ios::binary);

	if (file.fail())
	{
		cout << "\n\nError: failed to open file.\n\n";
	}
	else
	{
		file.write((char*)& aCircle, sizeof(aCircle));
	}

	do
	{
		cout << "Menu \n"
			 << " (1) Add Circle(s) \n"
			 << " (2) Find a Circle by ID \n"
			 << " (3) Exit \n"
			 << "Your Selection -> ";
		cin >> option;

		switch (option)
		{
		case 1:
			AddNewCircle(file);
			break;


		case 2:
			AccessCircle(file);
			cout << "\n\nId    radius" << endl;
			cout << aCircle.GetCircleId() << "     " << aCircle.GetCircleRadius() << "\n\n";
			break;


		case 3:
			file.close();
			break;


		default:
			cerr << "\nERROR: Wrong Option menu.\n\n";

		}

	} while (option != 3);

	return EXIT_SUCCESS;
}

The problem is that when i try to find the circles radius from the file by id it always prints 0 for id and 0 for radius...

???

In AccessCircle you never tested for errors on the open nor read. They are probably failing because you have the file open for writing. You also don't close the file after reading.

All IO needs and OPEN and CLOSE. And always test to make sure the OPEN, CLOSE, READ and WRITE worked.

You should not keep the file open for write all the time. Just open it when you need to write then close it. Be sure to open it for append (ios::app I believe)

I made some modifications, but it still not working properly. Any help, tips would much appreciated !

Circle.h

#ifndef CIRCLE_H
#define CIRCLE_H

#include <iostream>
#include <fstream>
using namespace std;

class Circle
{
	friend ostream& operator <<(ostream& output, const Circle& aCircle);
	friend istream& operator >>(istream& input, Circle& aCircle);

public:
	Circle();
	Circle(double radius, int id);
	Circle(const Circle& aCircle);

	void SetCircleRadius(double radius) { _circleRadius = radius; }
	void SetCircleId(int id)   { _circleId = id; }

	double GetCircleRadius() const   { return _circleRadius; }
	int GetCircleId() const { return _circleId; }

private:
	double  _circleRadius;
	int     _circleId;
};

#endif

Circle.cpp

#include "Circle.h"

Circle::Circle()
{
	_circleId = 0;
	_circleRadius = 0.0;
}

Circle::Circle(double radius, int id)
{
	_circleId = id;
	_circleRadius = radius;
}

Circle::Circle(const Circle& aCircle)
{
	_circleId = aCircle._circleId;
	_circleRadius = aCircle._circleRadius;
}

ostream& operator <<(ostream& output, const Circle& aCircle)
{
	output << "\n          ------------" << endl;
	output << "          Id    radius" << endl;
	output << "          ------------" << endl;
	output << "          " << aCircle._circleId << "     " << aCircle._circleRadius << endl;
	output << "          ------------" << "\n\n";

	return (output);
}

istream& operator >>(istream& input, Circle& aCircle)
{
	int quantity;
	cout << "\nHow many circles do you want to add ";
	input >> quantity;

	for (int i = 0; i < quantity; ++i)
	{
		cout << "\n\nEnter the ID of Circle #" << (i + 1) << " : ";
		input >> aCircle._circleId;

		cout << "Enter Radius of Circle #" << (i + 1) << " : ";
		input >> aCircle._circleRadius;

		cout << endl;
	}

	return (input);
}

main.cpp

#include <iostream>
#include <conio.h>
#include <fstream>
using namespace std;

#include "Circle.h"

int main ()
{
	Circle aCircle;
	fstream file;
	int option;

	do
	{
		cout << "Menu \n"
			 << " (1) Add Circle(s) \n"
			 << " (2) Find a Circle by ID \n"
			 << " (3) Exit \n"
			 << "Your Selection -> ";
		cin >> option;

		switch (option)
		{
		case 1:
			file.close();
			file.clear();

			file.open("Circle.dat", ios::out | ios::app | ios::binary);
			
			if (!file)
			{
				cerr << "\n\nFailed to open file.\n\n";
				system("PAUSE");
				exit(1);
			}
			else
			{
				cin >> aCircle;
				file.write(reinterpret_cast<char*> (&aCircle), sizeof(Circle));
			}
			break;

		case 2:
			file.close();
			file.clear();


			cout << "Enter id: ";
			int id;
			cin >> id;
			aCircle.SetCircleId(id);

			file.open("Circle.dat", ios::in | ios::app | ios::binary);

			if (!file)
			{
				cerr << "\n\nFailed to open file.\n\n";
				system("PAUSE");
				exit(1);
			}
			else
			{
				file.seekg(id * sizeof(Circle), ios::beg);
				file.read(reinterpret_cast<char *> (&aCircle), sizeof(Circle));

				cout << aCircle;
			}	
			break;


		case 3:
			file.close();
			cout << "\n\nG   o    o    D    B    y    E\n\n";
			exit(0);
			break;


		default:
			cerr << "\nERROR: Wrong Option menu. Please try again.\n\n";

		}

	} while (option != 3);

	return EXIT_SUCCESS;
}

I made some modifications, but it still not working properly. Any help, tips would much appreciated !

OK. read the post titled Read Me: Read This Before Posting

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.