467,146 Members | 1,294 Online
Bytes | Developer Community
Ask Question

Home New Posts Topics Members FAQ

Post your question to a community of 467,146 developers. It's quick & easy.

Help with file processing

I need some assistance with random access file processing. I have a function
that I would like to change from sequential file processing to random
access. Thanks in advance.

void updatePower(string filename) {

ifstream in(filename.c_str(), ios::in);
int cnt = 0;

// read all records into database until we reach the end of the file
while (!in.eof()) {
database[cnt++].input(in);
}

in.close();

int id;
cout << "Enter entry ID to change balance:"; //for this using the
overloaded
cin >id;

// check array bounds for databse, 0 to 49
if (id<0 || id>49) {
cout << "illegal ID - abort." << endl;
return;
}

// enter new power
double power;
cout << "Enter new power:";
cin >power;

// set new customer balance
database[id].setupdatePower(power);

// write customers back to text file
ofstream ofs(filename.c_str(), ios::out);
for (int i=0;i<cnt-1;i++)
database[i].output(ofs);

ofs.close();
}
Dec 15 '06 #1
  • viewed: 1603
Share:
5 Replies

"B. Williams" <wi*******@hotmail.comwrote in message
news:%Z******************@newsfe23.lga...
>I need some assistance with random access file processing. I have a
function that I would like to change from sequential file processing to
random access. Thanks in advance.

void updatePower(string filename) {

ifstream in(filename.c_str(), ios::in);
int cnt = 0;

// read all records into database until we reach the end of the file
while (!in.eof()) {
database[cnt++].input(in);
}

in.close();

int id;
cout << "Enter entry ID to change balance:"; //for this using the
overloaded
cin >id;

// check array bounds for databse, 0 to 49
if (id<0 || id>49) {
cout << "illegal ID - abort." << endl;
return;
}

// enter new power
double power;
cout << "Enter new power:";
cin >power;

// set new customer balance
database[id].setupdatePower(power);

// write customers back to text file
ofstream ofs(filename.c_str(), ios::out);
for (int i=0;i<cnt-1;i++)
database[i].output(ofs);

ofs.close();
}
Do I need to provide more information? This is the first time I have posted
here and not gotten any replies.
Dec 16 '06 #2
"B. Williams" wrote:
"B. Williams" <wi*******@hotmail.comwrote in message
news:%Z******************@newsfe23.lga...
>>I need some assistance with random access file processing. I have a
function that I would like to change from sequential file processing to
random access. Thanks in advance.

void updatePower(string filename) {

ifstream in(filename.c_str(), ios::in);
int cnt = 0;

// read all records into database until we reach the end of the file
while (!in.eof()) {
database[cnt++].input(in);
}

in.close();

int id;
cout << "Enter entry ID to change balance:"; //for this using the
overloaded
cin >id;

// check array bounds for databse, 0 to 49
if (id<0 || id>49) {
cout << "illegal ID - abort." << endl;
return;
}

// enter new power
double power;
cout << "Enter new power:";
cin >power;

// set new customer balance
database[id].setupdatePower(power);

// write customers back to text file
ofstream ofs(filename.c_str(), ios::out);
for (int i=0;i<cnt-1;i++)
database[i].output(ofs);

ofs.close();
}
Do I need to provide more information? This is the first time I have
posted here and not gotten any replies.
I don't know what you want to know. I consider it risky to use random
access to a text file because of the machinations that may be going on out
of your sight. Look into tellp, tellg, seekp and seekg. To read a record
you need to have a way to get the offset of that record so you can do a
seekg.
Dec 16 '06 #3

B. Williams wrote in message ...
>
"B. Williams" <wi*******@hotmail.comwrote in message...
>>I need some assistance with random access file processing. I have a
function that I would like to change from sequential file processing to
random access. Thanks in advance.

void updatePower(string filename) {
ifstream in(filename.c_str(), ios::in);
int cnt = 0;
// read all records into database until we reach the end of the file
while (!in.eof()) {
database[cnt++].input(in);
}
in.close();
int id;
cout << "Enter entry ID to change balance:"; //for this using the
//
overloaded
> cin >id;
// check array bounds for databse, 0 to 49
if (id<0 || id>49) {
cout << "illegal ID - abort." << endl;
return;
}
// enter new power
double power;
cout << "Enter new power:";
cin >power;
// set new customer balance
database[id].setupdatePower(power);
// write customers back to text file
ofstream ofs(filename.c_str(), ios::out);
for (int i=0;i<cnt-1;i++)
database[i].output(ofs);
ofs.close();
}
Do I need to provide more information?
Ahh, finally a question!! Yes, you need to tell *exactly* what you want to
do, what the code you showed is doing and what it is not doing (that you
expect).
There are many posts in this NGs archive that show why 'while(x.eof())' often
produces an extra loop.
You also failed to show what 'database' is.

I'd forget about 'random file access', and work out of memory (assuming the
whole file will fit).

std::vector<std::stringdata;

void updatePower( string filename ){
ifstream in( filename.c_str() );
if(!in){ throw "ERROR: Open ";} // or something
for( std::string line; std::getline( in, line ); ){
data.push_back( line );
}
in.close();
// --- use 'data' ---
// --- change 'data' ---
// --- write 'data' back to file ---
ofstream ofs( filename.c_str() );
if( not ofs ){ throw "ERROR: Write ";} // or something
for( size_t i(0); i < data.size(); ++i ){
ofs<<data[ i ]<<std::endl;
}
ofs.close();
return;
} // updatePower(string)

Reading a chunk from the middle of a file is fairly easy if you know exactly
where the chunk is. Writeing a chunk in the middle of a file is where
everything goes south for the winter. (It depends on the file system used
(there are hundreds), and C++ does not address 'file system specific' things.
(..and needs a std lib to even know that there is a file system! <G>))

You could set the write point using 'seekp' (std::ios_base::ate). But, when
you write to that spot, the rest of the file would be truncated, so, you'd
need to copy the rest of the file to that point. (loosely speaking)
The easier way in C++ is to read file, modify, write file.

--
Bob R
POVrookie
Dec 16 '06 #4

"BobR" <Re***********@worldnet.att.netwrote in message
news:TN*********************@bgtnsc04-news.ops.worldnet.att.net...
>
B. Williams wrote in message ...
>>
"B. Williams" <wi*******@hotmail.comwrote in message...
>>>I need some assistance with random access file processing. I have a
function that I would like to change from sequential file processing to
random access. Thanks in advance.

void updatePower(string filename) {
ifstream in(filename.c_str(), ios::in);
int cnt = 0;
// read all records into database until we reach the end of the file
while (!in.eof()) {
database[cnt++].input(in);
}
in.close();
int id;
cout << "Enter entry ID to change balance:"; //for this using the
//
overloaded
>> cin >id;
// check array bounds for databse, 0 to 49
if (id<0 || id>49) {
cout << "illegal ID - abort." << endl;
return;
}
// enter new power
double power;
cout << "Enter new power:";
cin >power;
// set new customer balance
database[id].setupdatePower(power);
// write customers back to text file
ofstream ofs(filename.c_str(), ios::out);
for (int i=0;i<cnt-1;i++)
database[i].output(ofs);
ofs.close();
}
Do I need to provide more information?

Ahh, finally a question!! Yes, you need to tell *exactly* what you want to
do, what the code you showed is doing and what it is not doing (that you
expect).
There are many posts in this NGs archive that show why 'while(x.eof())'
often
produces an extra loop.
You also failed to show what 'database' is.

I'd forget about 'random file access', and work out of memory (assuming
the
whole file will fit).

std::vector<std::stringdata;

void updatePower( string filename ){
ifstream in( filename.c_str() );
if(!in){ throw "ERROR: Open ";} // or something
for( std::string line; std::getline( in, line ); ){
data.push_back( line );
}
in.close();
// --- use 'data' ---
// --- change 'data' ---
// --- write 'data' back to file ---
ofstream ofs( filename.c_str() );
if( not ofs ){ throw "ERROR: Write ";} // or something
for( size_t i(0); i < data.size(); ++i ){
ofs<<data[ i ]<<std::endl;
}
ofs.close();
return;
} // updatePower(string)

Reading a chunk from the middle of a file is fairly easy if you know
exactly
where the chunk is. Writeing a chunk in the middle of a file is where
everything goes south for the winter. (It depends on the file system used
(there are hundreds), and C++ does not address 'file system specific'
things.
(..and needs a std lib to even know that there is a file system! <G>))

You could set the write point using 'seekp' (std::ios_base::ate). But,
when
you write to that spot, the rest of the file would be truncated, so, you'd
need to copy the rest of the file to that point. (loosely speaking)
The easier way in C++ is to read file, modify, write file.

--
Bob R
POVrookie
Bob,
I'll post the entire program. I wrote this code to process files, but now I
need to modify it for random access file processing.

#include <iostream>
using std::cin;
using std::cout;
using std::endl;
using std::ios;
using std::cerr;

using std::ostream;
using std::istream;
#include <cstring>

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

#include <string>
using std::string;
class PPG{
public:
PPG(char *a, char b, int c)
{ dresscolor =b;
power = c;
setname(a);}//end constructor 1

PPG()
{ setname("Ms.Bellum");
dresscolor ='p';
power = 0;
}//end default constructor

char *getname()const {return name;}

void setname(char *a){
int l =strlen(a);
name = new char[l+1];
strcpy(name,a);
name[l] = '\0';
}//end setname
void output(ostream & out) {
out << name << ' ' << dresscolor << ' ' << power << endl;
}

void input(istream &in) {
in >name >dresscolor >power;
}
void setupdatePower(double p) { power = p; }
int getpower() const{return power;}
void setpower(int z){power = z;}
char getdresscolor() const{return dresscolor;}
void setdresscolor(char v){dresscolor=v;}
void print() const
{

ofstream outGirlsFile( "girls.txt", ios::app); //if I change this to in
if (!outGirlsFile)//instead of app then my file won't have any repeat
{
cerr << "File could not be opened" << endl;
exit(1);
}

outGirlsFile <<name << " " << dresscolor << " " << power << "\n";

cout <<name << " likes to wear ";

switch (dresscolor){
case 'g': case 'G':
cout <<"green dresses. She uses her ";break;
case 'b':case 'B':
cout <<"blue dresses. She uses her ";break;
case 'p': case 'P':
cout <<"pink dresses. She uses her ";
}//end switch
if (power == 1)
{
cout << "ice breath to defeat her enemies.\n";
}
else if (power ==2)
{
cout << "ability to talk to squirrels to confuse evil villians.\n";
}
else if (power ==3)
{
cout <<"bad attitude to stop evil doers.\n";
}
else
cout <<"girl power to rule the world.\n";
}//end print

bool operator==(PPG &ppg)
{ return (strcmp(name, ppg.name)==0); }

private:
char * name;
char dresscolor; //g-reen, b-lue, p-pink
int power; //1-ice breath, 2- squirrel speak, 3-bad attitude
}; //end class

void outputLine( char *, char, int);

PPG database[50];

// list all entry records already store in our file
void ListAllRecords(string filename) {

ifstream in(filename.c_str(), ios::in); // create input stream to file
PPG p; // use entry object to hold data
int count=0; // keep track of how many entries
// are in the file

// test to see if file exists, if not 'in.is_open()'returns false
if (!in.is_open()) {
cout << "No Records to display." << endl;
return;
}

// read each entry and store in our array of entries called 'database'
while (!in.eof())
database[count++].input(in);
in.close();

// display entries to the screen by sending cout to the ppg::output
function
for (int i=0;i<count-1;i++) {
cout << i << ") ";
database[i].output(cout);
}
}

void updatePower(string filename) {

// open text file for reading
ifstream in(filename.c_str(), ios::in);
int cnt = 0;

// read all records into database until we reach the end of the file
while (!in.eof()) {
database[cnt++].input(in);
}

// close text file
in.close();
int id;
cout << "Enter entry ID to change balance:";
cin >id;

if (id<0 || id>49) {
cout << "illegal ID - abort." << endl;
return;
}

// enter new power
double power;
cout << "Enter new power:";
cin >power;

// set new customer balance
database[id].setupdatePower(power);

// write customers back to text file
ofstream ofs(filename.c_str(), ios::out);
for (int i=0;i<cnt-1;i++)
database[i].output(ofs);

ofs.close();
}

main.cpp
#include "ppg.h" //note iostream is included in ppg.h so it is indirectly
included here

#include <string>
using std::string;

int main()
{

PPG p1; //here's a call to our default constructor
p1.print();
PPG girl1("Bubbles", 'b', 2);
girl1.print();
PPG badgirl("Princess",'g', 4);
badgirl.print();

cout << endl;
cout << "1) list all records from file girls.txt " << endl;
cout << "2) change the power for a name" << endl;
cout << "3) Quit." << endl;
cout << endl;

int choice=0;
string filename="girls.txt"; // name of our text file

while (choice!=3) {

cout << "Enter choise(1-3):";
cin >choice;

switch(choice) {
case 1:
ListAllRecords(filename);
break;
case 2:
updatePower(filename);
break;
}

}
return 0;
}//end main
Dec 17 '06 #5

B Williams wrote in message ...
>
Bob,
I'll post the entire program. I wrote this code to process files, but now I
need to modify it for random access file processing.

class PPG{ public:
PPG(char *a, char b, int c){ dresscolor =b;
power = c;
setname(a);}//end constructor 1

PPG(){ setname("Ms.Bellum");
dresscolor ='p';
power = 0;
}//end default constructor
Use init lists for both of those constructors.
>
void setname(char *a){
int l =strlen(a);
name = new char[l+1];
Where do you delete[] that allocation? If you don't, it's a memory leak.
Where is your destructor?
Use std::string.
strcpy(name,a);
name[l] = '\0';
}//end setname
void output(ostream & out) {
How do you know 'out' is in a good state?
out << name << ' ' << dresscolor << ' ' << power << endl;
How do you know 'out' is in a good state?
}

void input(istream &in) {
How do you know 'in' is in a good state?
Hint: check for 'in.is_open()'.
in >name >dresscolor >power;
How do you know 'in' is in a good state?
Hint: return a bool. ( return in.fail(); )
}

private:
char * name;
S/b std::string
char dresscolor; //g-reen, b-lue, p-pink
int power; //1-ice breath, 2- squirrel speak, 3-bad attitude
}; //end class

PPG database[50];
S/b std::vector<PPGdatabase( 50 ); // or std::list
>
// list all entry records already store in our file
void ListAllRecords(string filename) {
// PPG p; // use entry object to hold data

Never used, remove it.
int count=0; // keep track of how many entries
// are in the file
// test to see if file exists, if not 'in.is_open()'returns false
// read each entry and store in our array of entries called 'database'
while (!in.eof())
database[count++].input(in);
Does your last line show up twice?
>}

// // --- main.cpp ---

#include <iostream>
#include <string>
>#include "ppg.h" //note iostream is included in ppg.h so it is indirectly
included here

int main(){
using std::string;
>
return 0;
}//end main

I thought you had a better 'class PPG' from last time. What happened?
What makes you think you need a 'random file access'?

--
Bob R
POVrookie
Dec 18 '06 #6

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

reply views Thread by Maxwell Hammer | last post: by
4 posts views Thread by Ganesh Muthuvelu | last post: by
1 post views Thread by Rahul | last post: by
5 posts views Thread by Sam | last post: by
3 posts views Thread by RedRoses | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.