Sponsor for PC Pals Forum

Author Topic: c++ binary file ops  (Read 7167 times)

Offline davypipes

  • Regular Member
  • **
  • Posts: 31
c++ binary file ops
« on: November 20, 2004, 09:26 »
hi guys!!!
ive been making this program thats supposed to store a number of records to a binary file.the problem ive encountered is with placing a record in a temporary object so that i can later on work on that data.i defined a class for this purpose as follows:

class temp
{
public:

 char farmerName[20];
  long idNumber;
  long accountNumber;
  char location[30];
 };

 and passed on the info from the file  as follows:

// function to edit the farmer details...
void Farmer::editFarmer()
{
fstream myfile("Farmer.dat",ios::in | ios::out | ios::binary) ;

   temp temprec;
   clrscr();
   cout<<"\t\tYOU HAVE CHOSEN TO EDIT A RECORD \n";
   cout<<"\t\t------------------------------------\n\n";

while(myfile>>farmerName>>idNumber>>accountNumber>>location)
 {

temprec.farmerName=farmerName;
//error raised on previous line:Lvalue required

temprec.idNumber=idNumber;

temprec.accountNumber=accountNumber;

temprec.location=location;
//error raised on previous line:Lvalue required

 }
}

the error ive been gettting is been raissed when i pass the farmername and the location variables which are both of type char.the rest seems to be working fine ...its just those 2 lines!!!

so ....anyone?? :-\



Offline Sandra

  • Ultimate Member
  • *******
  • Posts: 12155
Re:c++ binary file ops
« Reply #1 on: November 20, 2004, 12:41 »
Sorry, I havent a clue about that stuff, hopefully someone will be along soon who may be able to help you out  ???

Offline Simon

  • Administrator
  • *****
  • Posts: 77923
  • First to score 7/7 in Quiz of The Week's News 2017
Re:c++ binary file ops
« Reply #2 on: November 20, 2004, 14:03 »
Another job for Dack, me thinks.   ;)
Many thanks to all our members, who have made PC Pals such an outstanding success!   :thumb:

Offline Dack

  • Established Member
  • ****
  • Posts: 831
Re:c++ binary file ops
« Reply #3 on: November 20, 2004, 19:00 »
http://www.parashift.com/c++-faq-lite/serialization.html#faq-35.6

In other words, storing character data is not really recommended that way as you are never exactly sure where it's going to end.

Better to use the Read() and Write() functions for the character and location fields.

Assuming the farmerName and location variables are defined as per the structure i.e. char [ 20 ].

Remember that (in most instances) temprec.farmerName is actually an address - equivalent to &temprec.farmerName[ 0 ]. If you use that in your code you should see the error :)

i.e. you are trying to say:
&temprec.farmerName[ 0 ]= &farmerName[ 0 ]

You could use a memcpy(temprec.farmerName, farmerName, sizeof(temprec.farmerName)); to get rid of the error.
hey promised the earth! Then delivered mud.
Technically it did meet the spec.

Offline davypipes

  • Regular Member
  • **
  • Posts: 31
Re:c++ binary file ops
« Reply #4 on: November 22, 2004, 14:18 »
hmmmm.....
so i gueess lem me try out the write() and read() functions!! hopefully all will go well and thanks for the advice!! ;)

Offline davypipes

  • Regular Member
  • **
  • Posts: 31
Re:c++ binary file ops
« Reply #5 on: November 29, 2004, 14:59 »
ok!!! thats it....i really need someone with a good idea on how am to edit the farmer records!!!!rather ...how am supposed to edit a farmer's details,eg name...location..acc number!!!
 heres what ive been able to do so far!!!!
#include<fstream.h>
#include<conio.h>
#include<iomanip.h>
#include<stdio.h>
/*

*************************************************************
program description
*************************************************************

this is  a program for storing farmers records
the functions include:
registering farmers
searching for a specific farmer
viewing farmer records!
*************************************************************
*/
class Farmer
{
  char farmerName[20];
  long idNumber;
  long accountNumber;
  char location[30];

  public:
   void mainMenu();
   void registerFarmer();
   void searchFarmer();
   void viewFarmer();
   //void editfarmer();

};
void waitmsg()
{
   cout<<"PRESS RETURN [enter]TO EXIT";
   getchar();
}

//procedure for printing a record
 void Farmer::viewFarmer()
  {

   int i=1;
   ifstream myfile("Farmers.dat",ios::in) ;
   clrscr();
    cout<<"         LIST OF ALL REGISTERED FARMERS \n\n"<<endl;
    cout<<" "<<setw(5)<<"FARMER NAME"<<setw(17)<<"ID NUMBER"<<setw(17)<<"ACCOUNT NUMBER"<<setw(17)<<"LOCATION"<<setw(17)<<endl;
    cout<<"-----------------------------------------------------------------------------"<<endl<<endl;
    while(myfile>>farmerName>>idNumber>>accountNumber>>location)
       {
         cout <<i<<"   "<<setw(7)<<farmerName<<setw(18)<<idNumber<<setw(17)<<accountNumber<<setw(17)<<location<<setw(17)<<endl<<endl;
         i++;
       }
       cout<<"\n-------------------------END OF RECORDS----------------------------"<<endl;
      myfile.close();
      waitmsg();
   }



void Farmer::registerFarmer()
{
   ofstream myfile("Farmers.dat",ios::app);
   clrscr();

   char choice ='y';
      while (choice=='y' || choice=='Y')
        {
            clrscr();
            cout<<"\t\tYOU HAVE CHOSEN TO REGISTER A NEW FARMER \n";
            cout<<"\t\t----------------------------------------\n\n";
            cout <<"Please type in the details for the farmer \n\n";
            cout <<"Farmer Name :";             cin >>farmerName;
            cout <<"\nFarmer ID Number :";      cin >>idNumber;
            cout <<"\nFarmer Account Number :"; cin  >>accountNumber;
            cout <<"\nPhysical Location :";    cin  >>location;

            //save the entered data to file*/
            myfile<<farmerName<<" "<<idNumber<<" "<<accountNumber<<" "<<location<<" \n"  ;

            cout <<"Dou you want to enter another record Y(es) N(o) ?";
            cin  >> choice;
        }
      myfile.close();
    }

//function to edit the record..
//heres tthe problem area....
/*void editfarmer()
{

} */


/*procedure for searching a record */
void Farmer::searchFarmer()
   {
      ifstream myfile("a:Farmers.dat",ios::in);

      long int searchkey;
      clrscr();
      cout<<"\t\tYOU HAVE CHOSEN TO SEARCH FOR A FARMER \n";
      cout<<"\t\t----------------------------------------\n\n";
      cout<<"Please enter the account number of the farmer : ";
      cin>> searchkey;
      while((myfile>>farmerName>>idNumber>>accountNumber>>location) && (accountNumber != searchkey))
       {  }
           if(accountNumber == searchkey)
               {
                  cout <<"\n Farmer Name : "<<farmerName<<"\nFarmer ID Number : "<<idNumber<<"\nFarmer Account Number : "<<accountNumber<<"\nFarmer Location : "<<location<<endl<<endl;
               }
           else
           cout<<"\n \t \t Record not found !\n\n\n\n\n" ;

      cout<<"\n-------------------------END OF RECORDS----------------------------"<<endl;

      myfile.close();
      waitmsg();
    }
//Definition of function mainMenu
//Displays the main menu and asks the user to select


void Farmer::mainMenu(void)
{
   int Choice;

   do
   {
      clrscr();

      cout<<"\n\n\tWELCOME TO THE WATAMU DAIRY FARMERS COOPERATIVE SOCIETY\n\n\n\n";
      cout<<"\t\t|- - - - - - - - - - - - - - - -|\n" ;
      cout<<"\t\t|\tTAMU DAIRY FARMERS\t|\n";
      cout<<"\t\t|-------------------------------|\n";
      cout<<"\t\t|\t  FARMERS RECORDS\t|\n";
      cout<<"\t\t|\t1.Register New Farmer\t|\n";
      cout<<"\t\t|\t2.View Farmer Records\t|\n";
      cout<<"\t\t|\t3.Search Farmer Record\t|\n";
      cout<<"\t\t|\t4.edit Farmer Record\t|\n";
      cout<<"\t\t|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|\n\n " ;
      cout<<"\tEnter 1 , 2 , 3 , 4 , 5 or 6 :  ";
      cin>>Choice;


   }
   //when the choice is not among the options
   while (Choice < 1 || Choice > 4);



   switch (Choice)
    {
      case 1 :registerFarmer();mainMenu()      ;break;
      case 2 :viewFarmer();mainMenu()        ;break;
      case 3 :searchFarmer();mainMenu()        ;break;
     // case 4:editfarmer()mainmenu();break;
    }
}

void main()
{
   Farmer fDetails;
   fDetails.mainMenu();
}

Offline Simon

  • Administrator
  • *****
  • Posts: 77923
  • First to score 7/7 in Quiz of The Week's News 2017
Re:c++ binary file ops
« Reply #6 on: November 29, 2004, 17:00 »
Hopefully Dack will be along soon to help you with that!   :o
Many thanks to all our members, who have made PC Pals such an outstanding success!   :thumb:

Offline Dack

  • Established Member
  • ****
  • Posts: 831
Re:c++ binary file ops
« Reply #7 on: November 29, 2004, 21:56 »
*LOTS* to do here I'm afraid :( First question is what C++ compiler are you using - clrscr isn't a standard MS function you see but is in Borland C.

Lets start with the easy ones:

1. Your menu function is recursive which would lead to memory errors. There is also no way of exiting the program safely.

Your code:
Quote
void Farmer::mainMenu(void)
{
   int Choice;

   do
   {
      clrscr();

      cout<<"\n\n\tWELCOME TO THE WATAMU DAIRY FARMERS COOPERATIVE SOCIETY\n\n\n\n";
      cout<<"\t\t|- - - - - - - - - - - - - - - -|\n" ;
      cout<<"\t\t|\tTAMU DAIRY FARMERS\t|\n";
      cout<<"\t\t|-------------------------------|\n";
      cout<<"\t\t|\t  FARMERS RECORDS\t|\n";
      cout<<"\t\t|\t1.Register New Farmer\t|\n";
      cout<<"\t\t|\t2.View Farmer Records\t|\n";
      cout<<"\t\t|\t3.Search Farmer Record\t|\n";
      cout<<"\t\t|\t4.edit Farmer Record\t|\n";
      cout<<"\t\t|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|\n\n " ;
      cout<<"\tEnter 1 , 2 , 3 , 4 , 5 or 6 :  ";
      cin>>Choice;


   }
   //when the choice is not among the options
   while (Choice < 1 || Choice > 4);



   switch (Choice)
    {
      case 1 :registerFarmer();mainMenu()      ;break;
      case 2 :viewFarmer();mainMenu()        ;break;
      case 3 :searchFarmer();mainMenu()        ;break;
     // case 4:editfarmer()mainmenu();break;
    }
}


This works better if written as:
Quote
void Farmer::mainMenu(void)
{
   int Choice = 0;
   do
   {
     do
     {
      clrscr();

      cout<<"\n\n\tWELCOME TO THE WATAMU DAIRY FARMERS COOPERATIVE SOCIETY\n\n\n\n";
      cout<<"\t\t|- - - - - - - - - - - - - - - -|\n" ;
      cout<<"\t\t|\tTAMU DAIRY FARMERS\t|\n";
      cout<<"\t\t|-------------------------------|\n";
      cout<<"\t\t|\t  FARMERS RECORDS\t|\n";
      cout<<"\t\t|\t1.Register New Farmer\t|\n";
      cout<<"\t\t|\t2.View Farmer Records\t|\n";
      cout<<"\t\t|\t3.Search Farmer Record\t|\n";
      cout<<"\t\t|\t4.edit Farmer record\t|\n";
      cout<<"\t\t|\t5.Exit program\t\t|\n";
      cout<<"\t\t|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|\n\n " ;
      cout<<"\tEnter 1 , 2 , 3 , 4 , 5 or 6 :  ";
      cin>>Choice;


     }
     //when the choice is not among the options
     while (Choice < 1 || Choice > 5);



   switch (Choice)
    {
      case 1 :registerFarmer();break;
      case 2 :viewFarmer();break;
      case 3 :searchFarmer();break;
     // case 4:editfarmer()mainmenu();break;
     default: break;
    }
   }while (Choice != 5);
}
hey promised the earth! Then delivered mud.
Technically it did meet the spec.

Offline Dack

  • Established Member
  • ****
  • Posts: 831
Re:c++ binary file ops
« Reply #8 on: November 29, 2004, 22:32 »
2. Your registerfarmer routine doesn't check to see if the number already exists in the file - if so you should say that there is a duplicate entry.
Quote
void Farmer::registerFarmer()
{
   ofstream myfile("Farmers.dat",ios::app);
   clrscr();

   char choice ='y';
      while (choice=='y' || choice=='Y')
        {
            clrscr();
            cout<<"\t\tYOU HAVE CHOSEN TO REGISTER A NEW FARMER \n";
            cout<<"\t\t----------------------------------------\n\n";
            cout <<"Please type in the details for the farmer \n\n";
            cout <<"Farmer Name :";             cin >>farmerName;
            cout <<"\nFarmer ID Number :";     cin >>idNumber;
            cout <<"\nFarmer Account Number :"; cin  >>accountNumber;
            cout <<"\nPhysical Location :";    cin  >>location;

            //save the entered data to file*/
            myfile<<farmerName<<" "<<idNumber<<" "<<accountNumber<<" "<<location<<" \n"  ;

            cout <<"Dou you want to enter another record Y(es) N(o) ?";
            cin  >> choice;
        }
      myfile.close();
    }


Should be:
Quote
void Farmer::registerFarmer()
{

   clrscr();

   char choice ='y';
      while (choice=='y' || choice=='Y')
        {
            clrscr();
            cout<<"\t\tYOU HAVE CHOSEN TO REGISTER A NEW FARMER \n";
            cout<<"\t\t----------------------------------------\n\n";
            cout <<"Please type in the details for the farmer \n\n";
            cout <<"Farmer Name :";             cin >>farmerName;
            cout <<"\nFarmer ID Number :";     cin >>idNumber;
            cout <<"\nFarmer Account Number :"; cin  >>accountNumber;
            cout <<"\nPhysical Location :";    cin  >>location;

         // See if he already exists
         if (false==SearchForExisting(accountNumber))
         {
            //save the entered data to file
            ofstream myfile("Farmers.dat",ios::app);
            myfile<<farmerName<<" "<<idNumber<<" "<<accountNumber<<" "<<location<<" \n"  ;
            myfile.close();
         }
         else
         {
            cout << "\nFarmer already exists";
            cout << "\n" << farmerName<<" "<<idNumber<<" "<<accountNumber<<" "<<location<<" \n"  ;
         }
            cout <<"Do you want to enter another record Y(es) N(o) ?";
            cin  >> choice;
        }
    }
/*procedure for searching a record */
void Farmer::searchFarmer()
{

      long int searchkey;

     //      clrscr();
      cout<<"\t\tYOU HAVE CHOSEN TO SEARCH FOR A FARMER \n";
      cout<<"\t\t----------------------------------------\n\n";
      cout<<"Please enter the account number of the farmer : ";
      cin>> searchkey;

     if (true==SearchForExisting(searchkey))
     {
      cout <<"\n Farmer Name : "<<farmerName<<"\nFarmer ID Number : "<<idNumber<<"\nFarmer Account Number : "<<accountNumber<<"\nFarmer Location : "<<location<<endl<<endl;
      }
      else
        cout<<"\n \t \t Record not found !\n\n\n\n\n" ;

      cout<<"\n-------------------------END OF RECORDS----------------------------"<<endl;


      waitmsg();
}

// New function that searches for an existing record and reads the values
// into the buffer if we already have them
bool Farmer::SearchForExisting(long nSearchKey)
{
   // Initially show that we have not found the searchfield
   bool bRetVal = false;
   long nLocalAccountNumber = -1;
   long nLocalIDNumber = -1;
   char LocalFarmerName[20];
    char LocalLocation[30];
   // Open the file for reading
   ifstream myfile("C:Farmers.dat",ios::in);


    while((myfile>>LocalFarmerName>>nLocalIDNumber>>nLocalAccountNumber>>LocalLocation)
         && (nLocalAccountNumber != nSearchKey))
       {  };

   // indicate in the return that we have found the value
    // and update the values in out local record
    if(nLocalAccountNumber == nSearchKey)
    {
      idNumber = nLocalIDNumber;
      accountNumber = nLocalAccountNumber;
      strncpy(farmerName, LocalFarmerName, 20);
      strncpy(location, LocalLocation, 30);

      bRetVal = true;
   }
   // Close the file
   myfile.close();
   return bRetVal;
}


The searchforexisting function will be useful in a minute :)
hey promised the earth! Then delivered mud.
Technically it did meet the spec.

Offline Dack

  • Established Member
  • ****
  • Posts: 831
Re:c++ binary file ops
« Reply #9 on: November 30, 2004, 01:03 »
If you put those routines in then you'll see the problem I was on about concerning using write and read for the stream processing. If you open the farmers.dat file you'll see that each record you entered was a different size (because of the length of the text fields). You should now realise that you have to make all records the same (maximum size) in case you have to edit one and the new data will take up more space in the file than the existing data.

This involves simply changing the file input and output routines to use the read/write commands. We will then know how big each record is (20 bytes + the size of a long + the size of a long plus 30 bytes)

The edit routine then comes down to:
1. Get search key
2. find record that key matches
3. update fields in memory
4. open file for reading and writing
5. find place in file to change
6. write data
7. close file.

To make a read/write file you need to use the fstream type and the tellg and seekp operators.
hey promised the earth! Then delivered mud.
Technically it did meet the spec.

Offline Dack

  • Established Member
  • ****
  • Posts: 831
Re:c++ binary file ops
« Reply #10 on: November 30, 2004, 01:18 »
Full code to do what you are after is something like this.

You will need to properly modify the editing function (I just put the one field in).

Should be a good start for you though :)
Quote
// farmer.cpp : Defines the entry point for the console application.
//
#include <stdlib.h>
#include <string.h>

#include <iostream.h>
#include <fstream.h>
#include <conio.h>
#include <iomanip.h>
#include <stdio.h>
/*

*************************************************************
program description
*************************************************************

this is  a program for storing farmers records
the functions include:
registering farmers
searching for a specific farmer
viewing farmer records!
*************************************************************
*/
class Farmer
{
  char farmerName[20];
  long idNumber;
  long accountNumber;
  char location[30];

  public:
   void mainMenu();
   void registerFarmer();
   void searchFarmer();
   void viewFarmer();
   void editfarmer();
   bool   SearchForExisting(long nSearchKey);

};


void waitmsg()
{
   cout<<"PRESS RETURN [enter]TO EXIT";
   getchar();
}

//procedure for printing a record
void Farmer::viewFarmer()
  {

   int i=1;
   ifstream myfile("a:Farmers.dat",ios::in|ios::binary) ;
   clrscr();
    cout<<"        LIST OF ALL REGISTERED FARMERS \n\n"<<endl;
    cout<<" "<<setw(5)<<"FARMER NAME"<<setw(17)<<"ID NUMBER"<<setw(17)<<"ACCOUNT NUMBER"<<setw(17)<<"LOCATION"<<setw(17)<<endl;
    cout<<"-----------------------------------------------------------------------------"<<endl<<endl;
    while(!myfile.fail())
   {
      myfile.read(farmerName, sizeof(farmerName));
      myfile.read((char *)&idNumber, sizeof(idNumber));
      myfile.read((char *)&accountNumber, sizeof(accountNumber));
      myfile.read(location, sizeof(location));

      // now need to check there has not been an error in reading as the eof flag is not
      // set until a file read has been done - this means an empty file still runs through
      // here once
      if (!myfile.fail())
      {
         cout <<i<<"  "<<setw(7)<<farmerName<<setw(18)<<idNumber<<setw(17)<<accountNumber<<setw(17)<<location<<setw(17)<<endl<<endl;
         i++;
      }
   }
    cout<<"\n-------------------------END OF RECORDS----------------------------"<<endl;
    myfile.close();
    waitmsg();
   }



void Farmer::registerFarmer()
{

   clrscr();

   char choice ='y';
      while (choice=='y' || choice=='Y')
        {
        // clear out the variables
        memset(farmerName, sizeof(farmerName), 0);
        memset(location, sizeof(location),0);
        idNumber = 0;
        accountNumber = 0;

            clrscr();
            cout<<"\t\tYOU HAVE CHOSEN TO REGISTER A NEW FARMER \n";
            cout<<"\t\t----------------------------------------\n\n";
            cout <<"Please type in the details for the farmer \n\n";
            cout <<"Farmer Name :";             cin >>farmerName;
            cout <<"\nFarmer ID Number :";     cin >>idNumber;
            cout <<"\nFarmer Account Number :"; cin  >>accountNumber;
            cout <<"\nPhysical Location :";    cin  >>location;

         // See if he already exists
         if (false==SearchForExisting(accountNumber))
         {
            //save the entered data to file
            ofstream myfile("a:Farmers.dat",ios::app|ios::binary);
            myfile.write(farmerName, sizeof(farmerName));
            myfile.write((char *)&idNumber, sizeof(idNumber));
            myfile.write((char *)&accountNumber, sizeof(accountNumber));
            myfile.write(location, sizeof(location));
            myfile.close();
         }
         else
         {
            cout << "\nFarmer already exists";
            cout << "\n" << farmerName<<" "<<idNumber<<" "<<accountNumber<<" "<<location<<" \n"  ;
         }
            cout <<"Do you want to enter another record Y(es) N(o) ?";
            cin  >> choice;
        }
    }

//function to edit the record..
//heres tthe problem area....
void  Farmer::editfarmer()
{
   char cChoice = 'y';

   long nSearchKey = 0;
   
   long nLocalAccountNumber = -1;
   long nLocalIDNumber = -1;
   char LocalFarmerName[20];
    char LocalLocation[30];
   long   nPosition;

   // get the searchID
   cout << "Enter search key ";
   cin >> nSearchKey;
   // see if it already exists - due to the way the search is written
   // our variables contain the values we want to change
   if (true==SearchForExisting(nSearchKey))
   {
     // display existing record values
     cout << "\n" << farmerName<<" "<<idNumber<<" "<<accountNumber<<" "<<location<<" \n"  ;
         
     // allow them to be altered
     cout << "\nEnter new farmername";
     cin >> farmerName;
     // etc.. for all the fields

     // Do you really want to save?
     do{
        cout << "\nUpdate record (Y/N)";
        cin >> cChoice;
       cChoice = toupper(cChoice);
     } while  (('Y'!=cChoice)
            &&('N'!=cChoice));
     
     // If yes:
     if ('Y'==cChoice)
     {
      // open file for input and output
      fstream myfile("a:Farmers.dat",ios::in|ios::out|ios::binary);

      // read file until matching record
      while ( (!myfile.fail())&&
            (nSearchKey!=nLocalIDNumber))
      {
         // read into local variables
         myfile.read(LocalFarmerName, sizeof(LocalFarmerName));
         myfile.read((char *)&nLocalIDNumber, sizeof(nLocalIDNumber));
         myfile.read((char *)&nLocalAccountNumber, sizeof(nLocalAccountNumber));
         myfile.read(LocalLocation, sizeof(LocalLocation));
      }
      // we are now one record past the data we want to change so change the file pointer
      // back by the size of the record
      nPosition = myfile.tellg();

      // move back by record size
      nPosition -= sizeof(farmerName);
      nPosition -= sizeof(idNumber);
      nPosition -= sizeof(accountNumber);
      nPosition -= sizeof(location);

      // now set the pointer for where we are going to write
      // from the beginning of the file
      myfile.seekp(nPosition,ios::beg);


      // output the values of the data - overwriting existing record
      myfile.write(farmerName, sizeof(farmerName));
      myfile.write((char *)&idNumber, sizeof(idNumber));
      myfile.write((char *)&accountNumber, sizeof(accountNumber));
      myfile.write(location, sizeof(location));

      // now close the file
      myfile.close();

      cout << "\nEntry changed";
     }
     else
     {
      // If No: throw away the data -
        cout << "\n Discarding changes";
     }
   }
   else
   {
      // Record not found
      cout << "\nentry not found for that search key";
   }
   waitmsg();
}


/*procedure for searching a record */
void Farmer::searchFarmer()
{

      long int searchkey;

   clrscr();
      cout<<"\t\tYOU HAVE CHOSEN TO SEARCH FOR A FARMER \n";
      cout<<"\t\t----------------------------------------\n\n";
      cout<<"Please enter the account number of the farmer : ";
      cin>> searchkey;

     if (true==SearchForExisting(searchkey))
     {
      cout <<"\n Farmer Name : "<<farmerName<<"\nFarmer ID Number : "<<idNumber<<"\nFarmer Account Number : "<<accountNumber<<"\nFarmer Location : "<<location<<endl<<endl;
      }
      else
        cout<<"\n \t \t Record not found !\n\n\n\n\n" ;

      cout<<"\n-------------------------END OF RECORDS----------------------------"<<endl;


      waitmsg();
}

// New function that searches for an existing record and reads the values
// into the buffer if we already have them
bool Farmer::SearchForExisting(long nSearchKey)
{
   // Initially show that we have not found the searchfield
   bool bRetVal = false;
   long nLocalAccountNumber = -1;
   long nLocalIDNumber = -1;
   char LocalFarmerName[20];
    char LocalLocation[30];
   // Open the file for reading
   ifstream myfile("a:Farmers.dat",ios::in|ios::binary);


    while((!myfile.fail())&&
        (nLocalAccountNumber!=nSearchKey))
   {
      myfile.read(LocalFarmerName, sizeof(LocalFarmerName));
      myfile.read((char *)&nLocalIDNumber, sizeof(nLocalIDNumber));
      myfile.read((char *)&nLocalAccountNumber, sizeof(nLocalAccountNumber));
      myfile.read(LocalLocation, sizeof(LocalLocation));
     };

   // indicate in the return that we have found the value
    // and update the values in out local record
    if(nLocalAccountNumber == nSearchKey)
    {
      idNumber = nLocalIDNumber;
      accountNumber = nLocalAccountNumber;
      memcpy(farmerName, LocalFarmerName, 20);
      memcpy(location, LocalLocation, 30);

      bRetVal = true;
   }
   // Close the file
   myfile.close();
   return bRetVal;
}
//Definition of function mainMenu
//Displays the main menu and asks the user to select
void Farmer::mainMenu(void)
{
   int Choice = 0;

   // clear out all the variable space
   memset(farmerName, sizeof(farmerName), 0);
   memset(location, sizeof(location), 0);

   do
   {
     do
     {
      clrscr();

      cout<<"\n\n\tWELCOME TO THE WATAMU DAIRY FARMERS COOPERATIVE SOCIETY\n\n\n\n";
      cout<<"\t\t|- - - - - - - - - - - - - - - -|\n" ;
      cout<<"\t\t|\tTAMU DAIRY FARMERS\t|\n";
      cout<<"\t\t|-------------------------------|\n";
      cout<<"\t\t|\t  FARMERS RECORDS\t|\n";
      cout<<"\t\t|\t1.Register New Farmer\t|\n";
      cout<<"\t\t|\t2.View Farmer Records\t|\n";
      cout<<"\t\t|\t3.Search Farmer Record\t|\n";
      cout<<"\t\t|\t4.edit Farmer record\t|\n";
      cout<<"\t\t|\t5.Exit program\t\t|\n";
      cout<<"\t\t|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|\n\n " ;
      cout<<"\tEnter 1 , 2 , 3 , 4 , 5 or 6 :  ";
      cin>>Choice;


     }
     //when the choice is not among the options
     while (Choice < 1 || Choice > 5);



   switch (Choice)
    {
      case 1 :registerFarmer();break;
      case 2 :viewFarmer();break;
      case 3 :searchFarmer();break;
      case 4:editfarmer();break;
     default: break;
    }
   }while (Choice != 5);
}

void main()
{
   Farmer fDetails;
   fDetails.mainMenu();
}
hey promised the earth! Then delivered mud.
Technically it did meet the spec.

Offline davypipes

  • Regular Member
  • **
  • Posts: 31
Re:c++ binary file ops
« Reply #11 on: November 30, 2004, 09:59 »

Full code to do what you are after is something like this.

You will need to properly modify the editing function (I just put the one field in).

Should be a good start for you though :)
Quote
// farmer.cpp : Defines the entry point for the console application.
//
#include <stdlib.h>
#include <string.h>

#include <iostream.h>
#include <fstream.h>
#include <conio.h>
#include <iomanip.h>
#include <stdio.h>
/*

*************************************************************
program description
*************************************************************

this is  a program for storing farmers records
the functions include:
registering farmers
searching for a specific farmer
viewing farmer records!
*************************************************************
*/
class Farmer
{
  char farmerName[20];
  long idNumber;
  long accountNumber;
  char location[30];

  public:
   void mainMenu();
   void registerFarmer();
   void searchFarmer();
   void viewFarmer();
   void editfarmer();
   bool   SearchForExisting(long nSearchKey);

};


void waitmsg()
{
   cout<<"PRESS RETURN [enter]TO EXIT";
   getchar();
}

//procedure for printing a record
void Farmer::viewFarmer()
  {
....
....
...
   }



void Farmer::registerFarmer()
{
....
....
...

   clrscr();

   char choice ='y';        }
    }

//function to edit the record..
//heres tthe problem area....
void  Farmer::editfarmer()
{
   char cChoice = 'y';

   long nSearchKey = 0;
   
   long nLocalAccountNumber = -1;
   long nLocalIDNumber = -1;
   char LocalFarmerName[20];
    char LocalLocation[30];
   long   nPosition;

   // get the searchID
   cout << "Enter search key ";
   cin >> nSearchKey;
   // see if it already exists - due to the way the search is written
   // our variables contain the values we want to change
   if (true==SearchForExisting(nSearchKey))
   {
     // display existing record values
     cout << "\n" << farmerName<<" "<<idNumber<<" "<<accountNumber<<" "<<location<<" \n"  ;
         
     // allow them to be altered
     cout << "\nEnter new farmername";
     cin >> farmerName;
     // etc.. for all the fields

     // Do you really want to save?
     do{
        cout << "\nUpdate record (Y/N)";
        cin >> cChoice;
       cChoice = toupper(cChoice);
     } while  (('Y'!=cChoice)
            &&('N'!=cChoice));
     
     // If yes:
     if ('Y'==cChoice)
     {
      // open file for input and output
      fstream myfile("a:Farmers.dat",ios::in|ios::out|ios::binary);

      // read file until matching record
      while ( (!myfile.fail())&&
            (nSearchKey!=nLocalIDNumber))
      {
         // read into local variables
         myfile.read(LocalFarmerName, sizeof(LocalFarmerName));
         myfile.read((char *)&nLocalIDNumber, sizeof(nLocalIDNumber));
         myfile.read((char *)&nLocalAccountNumber, sizeof(nLocalAccountNumber));
         myfile.read(LocalLocation, sizeof(LocalLocation));
      }
      // we are now one record past the data we want to change so change the file pointer
      // back by the size of the record
      nPosition = myfile.tellg();

      // move back by record size
      nPosition -= sizeof(farmerName);
      nPosition -= sizeof(idNumber);
      nPosition -= sizeof(accountNumber);
      nPosition -= sizeof(location);

      // now set the pointer for where we are going to write
      // from the beginning of the file
      myfile.seekp(nPosition,ios::beg);


      // output the values of the data - overwriting existing record
      myfile.write(farmerName, sizeof(farmerName));
      myfile.write((char *)&idNumber, sizeof(idNumber));
      myfile.write((char *)&accountNumber, sizeof(accountNumber));
      myfile.write(location, sizeof(location));

      // now close the file
      myfile.close();

      cout << "\nEntry changed";
     }
     else
     {
      // If No: throw away the data -
        cout << "\n Discarding changes";
     }
   }
   else
   {
      // Record not found
      cout << "\nentry not found for that search key";
   }
   waitmsg();
}


/*procedure for searching a record */
void Farmer::searchFarmer()
{

      long int searchkey;

   clrscr();
      cout<<"\t\tYOU HAVE CHOSEN TO SEARCH FOR A FARMER \n";
      cout<<"\t\t----------------------------------------\n\n";
      cout<<"Please enter the account number of the farmer : ";
      cin>> searchkey;

     if (true==SearchForExisting(searchkey))
     {
      cout <<"\n Farmer Name : "<<farmerName<<"\nFarmer ID Number : "<<idNumber<<"\nFarmer Account Number : "<<accountNumber<<"\nFarmer Location : "<<location<<endl<<endl;
      }
      else
        cout<<"\n \t \t Record not found !\n\n\n\n\n" ;

      cout<<"\n-------------------------END OF RECORDS----------------------------"<<endl;


      waitmsg();
}

// New function that searches for an existing record and reads the values
// into the buffer if we already have them
bool Farmer::SearchForExisting(long nSearchKey)
{
   // Initially show that we have not found the searchfield
   bool bRetVal = false;
   long nLocalAccountNumber = -1;
   long nLocalIDNumber = -1;
   char LocalFarmerName[20];
    char LocalLocation[30];
   // Open the file for reading
   ifstream myfile("a:Farmers.dat",ios::in|ios::binary);


    while((!myfile.fail())&&
        (nLocalAccountNumber!=nSearchKey))
   {
      myfile.read(LocalFarmerName, sizeof(LocalFarmerName));
      myfile.read((char *)&nLocalIDNumber, sizeof(nLocalIDNumber));
      myfile.read((char *)&nLocalAccountNumber, sizeof(nLocalAccountNumber));
      myfile.read(LocalLocation, sizeof(LocalLocation));
     };

   // indicate in the return that we have found the value
    // and update the values in out local record
    if(nLocalAccountNumber == nSearchKey)
    {
      idNumber = nLocalIDNumber;
      accountNumber = nLocalAccountNumber;
      memcpy(farmerName, LocalFarmerName, 20);
      memcpy(location, LocalLocation, 30);

      bRetVal = true;
   }
   // Close the file
   myfile.close();
   return bRetVal;
}
//Definition of function mainMenu
//Displays the main menu and asks the user to select
void Farmer::mainMenu(void)
{
   int Choice = 0;

   // clear out all the variable space
   memset(farmerName, sizeof(farmerName), 0);
   memset(location, sizeof(location), 0);

   do
   {
     do
     {
      clrscr();

      cout<<"\n\n\tWELCOME TO THE WATAMU DAIRY FARMERS COOPERATIVE SOCIETY\n\n\n\n";
      cout<<"\t\t|- - - - - - - - - - - - - - - -|\n" ;
      cout<<"\t\t|\tTAMU DAIRY FARMERS\t|\n";
      cout<<"\t\t|-------------------------------|\n";
      cout<<"\t\t|\t  FARMERS RECORDS\t|\n";
      cout<<"\t\t|\t1.Register New Farmer\t|\n";
      cout<<"\t\t|\t2.View Farmer Records\t|\n";
      cout<<"\t\t|\t3.Search Farmer Record\t|\n";
      cout<<"\t\t|\t4.edit Farmer record\t|\n";
      cout<<"\t\t|\t5.Exit program\t\t|\n";
      cout<<"\t\t|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|\n\n " ;
      cout<<"\tEnter 1 , 2 , 3 , 4 , 5 or 6 :  ";
      cin>>Choice;


     }
     //when the choice is not among the options
     while (Choice < 1 || Choice > 5);



   switch (Choice)
    {
      case 1 :registerFarmer();break;
      case 2 :viewFarmer();break;
      case 3 :searchFarmer();break;
      case 4:editfarmer();break;
     default: break;
    }
   }while (Choice != 5);
}

void main()
{
   Farmer fDetails;
   fDetails.mainMenu();
}



hi thanks again for the insight..especially for the edit farmer function and the menu function on memory wastage...personally i hadnt thought about that...that recursion would bring me problems...anyway ...emmmm wat did i wanna say?....ooooh...yeah...ahh about the edit function..shouldnt i open the file first before displaying the record if found???or when the condition is been checked on this statement "   if (true==SearchForExisting(nSearchKey))", the file is already opened by the "searchforexisting()" function? and anyway within the function the file is closed?or does this have to do with the file buffers ur talking about ie: the data is still available in memeory even after closing a file?
am using the borland c++ compiler..which funny enuff doesnt identify the bool type!! :-\...


Offline Dack

  • Established Member
  • ****
  • Posts: 831
Re:c++ binary file ops
« Reply #12 on: November 30, 2004, 19:34 »

hi thanks again for the insight..especially for the edit farmer function and the menu function on memory wastage...personally i hadnt thought about that...that recursion would bring me problems...anyway ...emmmm wat did i wanna say?....ooooh...yeah...ahh about the edit function..shouldnt i open the file first before displaying the record if found???or when the condition is been checked on this statement "   if (true==SearchForExisting(nSearchKey))", the file is already opened by the "searchforexisting()" function? and anyway within the function the file is closed?or does this have to do with the file buffers ur talking about ie: the data is still available in memeory even after closing a file?
am using the borland c++ compiler..which funny enuff doesnt identify the bool type!! :-\...


BOOL is just an integer with 0 as FALSE and any non zero value as TRUE (Should be !0 = 0xFFFFFFFF really). You can use these yourself by doing the equivalent #defines at the top of the code. i.e.
#define bool int
#define true 0xFFFFFFFF
#define false 0

The search routine just:
1. opens file
2. reads a block of data in
3. checks to see if the end of file has been reached or the block is the one we are looking for
4. If block found the we already have the rest of the parameters in memory so we might as well just store them.
5. returns a value to say whether we found the data

I think one of the problems you have got with the skeleton code is that it is too specifically tied to one use - sort of going against the idea of code reusability that should be a feature of C++. You are only really using the class as an envelope. You could simply have renamed the menu function as main.

What I would have done is:
1. Define a class for the Farmer RECORD - functions to use include the standard Set/Get and overload of the << and >> operations.
2. Define a class that linked a passed filename to multiple farmer records and that supported record ADD, DELETE, VIEW and EDIT. This will be using instances of Class 1.
3. In a main application create an instance of the file class, open the file you want to use, and use the main application to perform the functions on Class 2. e.g get a record and add to file, edit existing record, display records etc.


hey promised the earth! Then delivered mud.
Technically it did meet the spec.

Offline Hiatus

  • Regular Member
  • **
  • Posts: 193
    • JoshSalverda.com
Re:c++ binary file ops
« Reply #13 on: November 30, 2004, 21:15 »
Wow....and to think that I'll be learning all this in the next few months...if that doesn't look like fun, i don't know what does!  ;D

Btw...just out of curiosity, how many programming languages do u know Dack?
l33t h@x0r... sort of...

Offline Dack

  • Established Member
  • ****
  • Posts: 831
Re:c++ binary file ops
« Reply #14 on: November 30, 2004, 23:22 »
Lets try and think back :)

High level recent ones:

C++, C, (Borland and Microsoft IDEs), Pascal, Visual Basic, Coral 66, JAVA

Low level (recent):
68000, 80x86, Microchip Pic, FR30, Mips, 6502, ADSP210x

Old languages (I used to use -or played with):
CESIL, True BASIC, USCD Pascal, Prolog, Pilot, Z80, Cobol

Couple of other odd uControllers too (from when I was writing DVD player code).

But it's possible to write Basic in any language :)

I tend to be involved in quite low level stuff (current stuff is device driver level under Windows NT for some legacy kit).
hey promised the earth! Then delivered mud.
Technically it did meet the spec.


Show unread posts since last visit.
Sponsor for PC Pals Forum