Write class data in file . dat, and at each use check if the information exists

Asked

Viewed 39 times

0

Good night, you guys. I’m writing a code for a university project. However, I’m having trouble manipulating the file in C++. I created a class called Stok and the amount of objects to be created are defined by the user via a >> Cin. Its members are: Symbol, amount, open_p, close_p, buy_p;` and mean:

Share Code; Quantity; Price Opening; Price Closing; Purchase Price.

My goal is to read this data from the . dat file to create some other functions in the program. I wonder how I could manipulate the lines in the file, for example, let’s say the file has 100 lines, how I could access the last two objects saved in the file and manipulate the opening price of these? Let’s say I want to perform a comparison between the "open_p" of the last two objects saved in the file. How could I do it? (Access the information in the file, store this value in a variable to later manipulate it in main. From now on, thank you very much and forgive me the lack of experience, I am beginner in C++.

#include <iostream>
#include <string>
#include <iomanip>
#include "stock.h"
#include <fstream>
#include <string>
using namespace std;

/* Written by Guilherme;  SENG1200  Final Project 
     Economic  Factor  -  Stocks Alarm System */ 
int main() 
{
    
    int stock_hold;
    string Symbol;
    int amount;
    double open_p;
    double close_p;
    double buy_p;
    
    ofstream stocks("Stockinfo.dat");   //data file created for recording
    

                 // first change of the second solution (user sets the value of stock_hold
                 cout << "Number of shares: ";
                 cin >> stock_hold;
                 //  defines the number of instances. 
  stock* stok[stock_hold];

    for (int i = 0; i < sizeof(stok)/sizeof(*stok); i++)
    {
        
         
        cout << "\n";
        stok[i] = new stock(Symbol, amount, open_p, close_p, buy_p);
        stocks << stok[i]->getSymbol();
        stocks << stok[i]->getVolume();
        stocks << stok[i]->getOpenP();
        stocks << stok[i]->getCloseP();
        stocks << stok[i]->getBuyP();       
    }
    stocks.close();

1 answer

1

In general it is not necessary or efficient to use the data directly from the disk. What is done is to read from the disk the set of client actions and keep in memory. At the end of the program, the updated data was recorded on the disk.

If it’s important you can keep one Journal of what is happening, an analytical record of the operations, and go recording on disk at each operation. So if the program aborts or something goes wrong you can read this file and from the original file and go redoing the transactions to return to the state of the moment of the crash.
If the program ends normally then you delete such history and life follows.

How to keep in memory? C++ has several convenient and flexible structures for this. Maybe you can consider a map for actions, which is like a dictionary indexed by the stock symbols. It’s "cute" and it’s easy. You can use a list, a vector, a set, things like that.

a simple class of action

class Stock
{
    string  Symbol;
    int     amount;
    double  open_p;
    double  close_p;
    double  buy_p;

    Stock(string, int, double, double, double);

};

Has the least.

a Property class

#pragma once
#include "Stock.h"
#include <map>

class Property
{
public:
    map<string, Stock>   my_stocks;

public:
    Property(string);
    Property() : Property("default.dat"){};

    int load_from_disk(string);
    int unload_to_disk(string);

};

It’s just a toy, to give you an idea: a stock record.

an example creating transactions

Imagine a function that would generate a random value purchase from a stock group, just to have some data to test the program, something like

pair<string, Stock>      stock_factory(int value)
{
    const string umas[] =
    {
        "LHDX",        "IRTC",        "PLBY",        "CAN",
        "TLSA",        "VECT",        "TSHA",        "AMD",
        "APPL",        "NVDA",        "AMZN",        "MSFT"
    };
    static int init = 999;
    if (value == 0) srand(210412); // reset rand()
    string symbol = umas[rand() % 12];
    Stock  stock(
        symbol,
        ++init,
        1. + rand() % 100 + rand() % 100 / 100.,
        1. + rand() % 100 + rand() % 100 / 100.,
        1. + rand() % 100 + rand() % 100 / 100.
    );
    pair <string, Stock> novo{ symbol, stock };
    return novo;
}

So every time you call that thing --- stock_factory() --- It returns a pair, a symbol and a "purchase", just to generate some data to put on the map. You have 12 possible actions, the amount will be numbered, the values are random.

And then you want to put it on a map where the shares are loaded by the symbol and each pair has the corresponding record... Like I said, the map is like a dictionary.

using it just to see the mechanics

int main(void)
{
    Property my_stocks;
    srand(210412);
    for (auto i = 0; i < 100; i += 1)
    {
        pair<string,Stock> nova = stock_factory(1);
        if (my_stocks.stock.find(nova.first) == my_stocks.stock.end())
        {
            cout << "Nova: " << nova.second.symbol << endl;
            my_stocks.stock.insert(stock_factory(1));
        }
        else
        {
            cout << "Compra: " << nova.second.symbol << 
                " + " << nova.second.amount << endl;
            my_stocks.stock[nova.first].amount += nova.second.amount;
        }
    }
    cout << "\n" << my_stocks.stock.size() << " Acoes na lista\n";

    for (auto uma : my_stocks.stock)
    {
        cout << 
            setw(4) << uma.first << ": " << 
            setw(6) << uma.second.amount <<
            " $" << uma.second.buy_p << "\n";
    }
}

This program creates my_stocks, a wallet.

And makes 100 transactions using the function stock_factory(). If a new action comes, put it on the map. If you already have it amount.

Then show how it turned out my_stocks.

It’s no use, I wrote just so you can see a possibility and think about the case. Here’s what the program shows:

Nova: AMD
Compra: TSHA + 1002
Nova: APPL
Nova: TLSA
Compra: IRTC + 1007
Nova: MSFT
Compra: LHDX + 1010
Nova: MSFT
Compra: IRTC + 1013
Compra: TSHA + 1014
Compra: LHDX + 1015
Nova: CAN
Compra: AMD + 1018
Nova: TLSA
Compra: PLBY + 1021
Compra: LHDX + 1022
Compra: AMD + 1023
Nova: MSFT
Compra: AMD + 1026
Nova: AMZN
Compra: PLBY + 1029
Compra: CAN + 1030
Compra: IRTC + 1031
Compra: IRTC + 1032
Nova: MSFT
Nova: MSFT
Compra: CAN + 1037
Compra: TLSA + 1038
Compra: PLBY + 1039
Compra: PLBY + 1040
Compra: TSHA + 1041
Nova: VECT
Compra: IRTC + 1044
Compra: APPL + 1045
Compra: PLBY + 1046
Compra: CAN + 1047
Compra: TLSA + 1048
Compra: TLSA + 1049
Compra: AMD + 1050
Compra: VECT + 1051
Compra: TSHA + 1052
Compra: VECT + 1053
Compra: PLBY + 1054
Nova: MSFT
Compra: AMD + 1057
Nova: NVDA
Compra: LHDX + 1060
Compra: AMD + 1061
Compra: IRTC + 1062
Compra: IRTC + 1063
Compra: MSFT + 1064
Compra: TSHA + 1065
Nova: NVDA
Compra: TSHA + 1068
Compra: CAN + 1069
Compra: APPL + 1070
Compra: MSFT + 1071
Nova: NVDA
Compra: PLBY + 1074
Compra: IRTC + 1075
Compra: PLBY + 1076
Compra: TSHA + 1077
Compra: VECT + 1078
Compra: AMD + 1079
Compra: APPL + 1080
Compra: LHDX + 1081
Compra: PLBY + 1082
Compra: AMD + 1083
Compra: TLSA + 1084
Compra: TLSA + 1085
Compra: TSHA + 1086
Nova: AMZN
Compra: LHDX + 1089
Compra: LHDX + 1090
Compra: IRTC + 1091
Compra: TLSA + 1092
Compra: LHDX + 1093
Compra: AMD + 1094
Compra: AMD + 1095
Compra: MSFT + 1096
Compra: APPL + 1097
Nova: NVDA
Compra: PLBY + 1100
Compra: APPL + 1101
Nova: NVDA
Compra: AMZN + 1104
Compra: TSHA + 1105
Compra: LHDX + 1106
Compra: MSFT + 1107
Compra: MSFT + 1108
Compra: LHDX + 1109
Compra: MSFT + 1110
Compra: TLSA + 1111
Compra: AMD + 1112
Compra: TSHA + 1113
Compra: APPL + 1114
Compra: LHDX + 1115
Compra: TLSA + 1116
Compra: AMZN + 1117
Compra: AMD + 1118

11 Acoes na lista
 AMD:  13828 $93.6
AMZN:   3324 $4.36
APPL:   7511 $22.79
 CAN:   5200 $38.33
IRTC:  10424 $58.56
LHDX:  12799 $71.03
MSFT:   7612 $2.89
PLBY:  11581 $90.15
TLSA:   9651 $14.07
TSHA:  11624 $89.85
VECT:   4225 $9.34

Here is the code: each class has two files, one with the declarations and the other with the code, and has the main() that is above...

#pragma once
#include <iostream>
using namespace std;


class Stock
{
public:
    string  symbol;
    int     amount;
    double  open_p;
    double  close_p;
    double  buy_p;

    Stock();
    Stock(string, int, double, double, double);

};
// fim de stock.h
#include "Stock.h"

Stock::Stock(string s, int a, double o, double c, double b) :
    symbol(s), amount(a), open_p(o), close_p(c), buy_p(b) {};

Stock::Stock() : symbol("???"), amount(0), open_p(0.), close_p(0.), buy_p(0.){};
// fim de stock.cpp
#pragma once
#include "Stock.h"
#include <map>

class Property
{
public:
    map<string, Stock>   stock;

public:
    Property(string);
    Property() : Property("default.dat"){};

    int load_from_disk(string);
    int unload_to_disk(string);

};
// fim de Property.h
#include "Property.h"

Property::Property(string filename) 
{
    //
}

int Property::load_from_disk(string filename)
{
    return 0;
}

int Property::unload_to_disk(string filename)
{
    return 0;
}
// fim de Property.cpp
#include "Property.h"
#include <iomanip>
#include <stdlib.h>

pair<string, Stock>      stock_factory(int);

int main(void)
{
    Property my_stocks;
    srand(210412);
    for (auto i = 0; i < 100; i += 1)
    {
        pair<string,Stock> nova = stock_factory(1);
        if (my_stocks.stock.find(nova.first) == my_stocks.stock.end())
        {
            cout << "Nova: " << nova.second.symbol << endl;
            my_stocks.stock.insert(stock_factory(1));
        }
        else
        {
            cout << "Compra: " << nova.second.symbol << 
                " + " << nova.second.amount << endl;
            my_stocks.stock[nova.first].amount += nova.second.amount;
        }
    }
    cout << "\n" << my_stocks.stock.size() << " Acoes na lista\n";

    for (auto uma : my_stocks.stock)
    {
        cout << 
            setw(4) << uma.first << ": " << 
            setw(6) << uma.second.amount <<
            " $" << uma.second.buy_p << "\n";
    }
}


pair<string, Stock>      stock_factory(int value)
{
    const string umas[] =
    {
        "LHDX",        "IRTC",        "PLBY",        "CAN",
        "TLSA",        "VECT",        "TSHA",        "AMD",
        "APPL",        "NVDA",        "AMZN",        "MSFT"
    };
    static int init = 999;
    if (value == 0) srand(210412); // reset rand()
    string symbol = umas[rand() % 12];
    Stock  stock(
        symbol,
        ++init,
        1. + rand() % 100 + rand() % 100 / 100.,
        1. + rand() % 100 + rand() % 100 / 100.,
        1. + rand() % 100 + rand() % 100 / 100.
    );
    pair <string, Stock> novo{ symbol, stock };
    return novo;
}
// fim de main.cpp

The main code is above. You can put it all together in one file if you want to try it like this. I recommend leaving it separate.

As you already have data you can write and test load_from_disk() and unload_to_disk(), using more than one Property...

If you want more or less data change the counter in main(), where it is with 100. And what you should save on the disk will already be on your screen to test...

  • Perfect, grandson. I loved the alternative, I found it very clever. Thank you very much, I will give a studied in the code above.

  • At the end of the program you have the data in my_stocks on the map. Then you can call my_stocks.unload_to_disk("dados"); and then declare Property outra("dados"); and test everything at the same time. If the answer is useful mark as such, so others can more easily find answers that have meaning.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.