Saurav Ghimire
Saurav Ghimire

Reputation: 540

How do I change the value of a variable in an object with file handling?

I am working on a project with oop and file handling and I need a changeQuantity() method where the name of the item and a number(positive or negative) is passed. I want to change the quantity with this method and write the changes to the file.

My Object:

    class Item(){
        int itemId, quantity;
        char title[25], type[10];
        float price;
        public:
            void changeQuantity(char*, int);
    };

The changeQuantity() method I am using:

    void Item::changeQuantity(char* name, int quan){
        fstream file;
        file.open("filename.txt", ios::in | ios::out);
        //after finding the object to work on
        this->quantity += quan;           
        file.seekp(file.tellp() - sizeof(*this)); 
        file.write((char*)this, sizeof(*this)); 
    }

I tried with this method but it messes up the entire text file. How can I change only the quantity variable and write that change to the file without affecting anything else????? Any kind of help would be greatly appreciated. Thank You.

PS: What I want to do here is only change the value of the quantity variable stored in the object which is stored in the txt file. The code that I am using messes the txt file.

Upvotes: 1

Views: 606

Answers (2)

Saurav Ghimire
Saurav Ghimire

Reputation: 540

I removed parameters except the file name from file.open() method. As fstream already has default parameters ios::in | ios::out, I removed that and it worked the way I wanted it to. But it does not work 100% of the time. It still repeats the problem sometimes and I haven't been able to find that out why.

Upvotes: 1

CodeLurker
CodeLurker

Reputation: 1371

It seems like you are mixing apples and oranges. You read something from a text file of size *this; but you read it into the binary storage of your object, and in binary mode. When it is written out, it is still in the binary format of your object. Ways to do it right:

  1. Open the file in text mode, and read and write everything with, say gets & puts (insecure and error prone). Translate every number from text to binary when reading it in.
  2. It is better to read them into std::string variables; as it is more powerful and less error prone. The classic C++ way to do it is e.g. the example from Input/output with files:
// reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main () {
  string line;
  ifstream myfile ("example.txt");
  if (myfile.is_open())
  {
    while ( getline (myfile,line) )
    {
      cout << line << '\n';
    }
    myfile.close();
  }

  else cout << "Unable to open file"; 

  return 0;
}

You would need to adapt it to read and translate (e.g. from text number format to a variable) each member of your object. I don't know of a way to mass read e.g. lines of text in a text file into an object's members. Once it is in binary format and properly read into your object, you can write our objects out to a binary file like that; but note: they won't be of fixed size, so you will need to write the size of the object out first, and then the object itself; and read the size of the object in and then the object itself.

In short, you are using a binary file access method, when e.g. your ints are text instead of probably 32-bit binaries, and your strings are are \n or \n\r instead of null terminated. Typical ways to handle text input and output of objects are to have one text line for each member, and translate them one at a time; or to read and write them as CSV or JSON - again one at a time for each member; and then looping through the file.

BTW: It is considered bad form to use using std; as in this example. To keep things in the std namespace from interfering with your variables and routines, it is better to use using std::string; etc.; for each thing you want to access from the std namespace.

Upvotes: 0

Related Questions