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;
}

The searching from the file is not working properly ????

main.cpp line 54: ios::app is only for output files, not input, so you might as well remove that from the open statement.

The main reason your program doesn't work is because of the way you are writing out the records. So NOT use ios::app (append) in the open statement, and before writing seekp() to the correct location, very similar to how you did it in main.cpp line 64. Do the same thing at main.cpp line 39.

>>Didn't work...
what didn't work. I can't help you if you don't post your most recent attempt. Just saying something didn't work does not help at all.

I think the ios::app is absolutely necessary in the output option, otherwise every new circle will overwrite the previous data (default file open mode is ios::trunc). ios::app has no meaning to an input file action, as AD said.

In the search section, you ask user for circle ID. Then you use that to index into the file to find a circle. But, when you enter circles, the user can enter any value for ID, can't they? So is there any correspondence?

For that matter, your circle input ( >> overload) asks how many circles to enter, and allows the user to enter multiple circle data. But it all is stored to the same circle object, each input overwriting the previous. Usually the input operator should not display prompts - it should just grab input from the stream and store it to the correct data member, so that you can use it with any stream. How would this implementation work reading from a text file with circle data? Not well.

What if i make the Id and array of 100 Id's that way they will not be replaced. Right ????

First, clarify what the problem is you're trying to solve. It's not really clear from the code.

Once you have a good definition for the circle class, you can do whatever you want with it in your main( ). Input a circle, write it to file. Create an array of circles (not of IDs), write or read the collection to file. All depends on what you want to do.

I think the ios::app is absolutely necessary in the output option, otherwise every new circle will overwrite the previous data (default file open mode is ios::trunc). ios::app has no meaning to an input file action, as AD said.
.

ios::app means

(append) Set the stream's position indicator to the end of the stream before each output operation.

With that flag it isn't possible to write a record in any random place in the file. The default is not ios::trunc -- you have to set that flag specifically if you want the file truncated each time it is open.

int main()
{
    string word;
    fstream out("myfile.dat",ios::out | ios::binary);
    out << "Hello World\r\n";
    out.close();
    out.clear();
    out.open("myfile.dat",ios::out | ios::binary);
    out << "Hello World\r\n";
    out.close();
    out.clear();
    out.open("myfile.dat",ios::in | ios::binary);
    while( out >> word)
        cout << word << "\n";
    return 0;
}
Comments
I also was working under a couple false assumptions. Learned something today.

AD, I run your sample, and only one instance of "hello world" exists in the file. It is being truncated at the second file opening operation.

ios::app sets the initial position of the file pointer to end of file when it's opened, so previous content is preserved. If you want random access to the file (read/write anywhere), preserving previous content, use mode ios::ate (At End).

Now I'm gonna have to set up a test - what happens if file opened in ios::app mode and I try to seek to a previously existing position and write something new?

--Added--
For random writing within existing file content, use ios:: in | ios::out | ios::ate. Without also having the in mode, you can't go backwards from end of file.

ios::app, even when set up as above, will not seek to previous portion of file.

Val

Comments
You are right. My test was not doing what I thought it did.
This article has been dead for over six months. Start a new discussion instead.