Thread: File I/O (Reading from a Random-Access File)

1. File I/O (Reading from a Random-Access File)

INFO:
The program should enter a circle radius and Id for that circle to a file, then it should search for that id and print the radius for that circle.

PROBLEM:
This program compiles but it's not searching properly.

Circle.h
Code:
```#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 SetCircleId(int id)   { _circleId = id; }

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

private:
int     _circleId;
};

#endif```
Circle.cpp
Code:
```#include "Circle.h"

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

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

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

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) << " : ";

cout << endl;
}

return (input);
}```
main.cpp
Code:
```#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;
}```

2. If I do your homework, do I get the A?

I will say that you are overcomplicating that class. You should probably think more along the lines of a linked list.

3. I've done my homework, I just need a little help.

& linked list ???

4. A linked list is a method of storing multiple objects in memory as a list that can be searched and updated at run time. Objects can be added or removed fom the list by linking or unlinking them into the chain. Each object contains 1 or more pointers and the data for the object itself. The individual links are usually dynamically allocated in memory on creation and free'd on deletion.

Basically its a way to store items when you dont know how many there will be at compile time.

Its perfect for this example because they are easy to implement as a class and you can add any number of object to the list up to the limit of RAM.

a link struct -
Code:
```struct LINK {
LPVOID Next;
LPVOID Prev;
LPVOID pObject;
};```

5. I don't think it's that good idea to use defines or typedefs such as LPVOID. It can confuse and it typically used with Windows API to specify what type it takes.
And I object to the bracket placement. K&R style is like this:
Code:
```struct LINK {
void* Next;
void* Prev;
void* pObject;
};```
It's easier for the eye and the brain.
However, since this is C++, I'd also recommend a type-safe struct in such case, unless you haven't learn templates yet:
Code:
```template<typename T> struct LINK {
T* Next;
T* Prev;
T* pObject;
};```

6. The archive has many circles, I only need to search for 1 at a time, that means only 1 object in memory..

7. the next and prev should not be void *, they should be LINK *.

8. Originally Posted by Elysia
And I object to the bracket placement.
Elysia, you sound like an ex-girlfirend of mine, are you applying for the vacancy?

As for using template, the guy is just learning the basics, there is no point in throwing too much at him too fast. Stick to basic types, yeah im just so used to using LPVOID I shoudl have used void*, but thats better than using templates.

yes Next and Prev should be LINK*

It's late in the day, my fingers are numb and the weed is wearing off...

9. Asking for the ID on input doesn't make sense. The user has no control over this. The ID should be a counter starting at zero, incremented for each new circle.

10. Im thinking maybe its intended for entering from a list only certain items. Like a job completion database where you enter the ID of the completeed jobs as they finish, btu have to leave room for the ones that arent finished yet and may have their ID assigned by some other process.

11. Then he needs to seek before writing.

12. Agreed.

13. I added a file.seekp(ios::beg) before writing, still not searching properly.

14. No, you misunderstand.

But perhaps you can first describe what you do, what you expect to happen, and what actually happens. Because that's far more interesting than "it doesn't work".

15. I hope this screen shot gives you an idea of what I'm trying to do.

http://i29.tinypic.com/ip9xkk.jpg

Popular pages Recent additions