Home > Mobile >  How to use pointer with struct to refer to the field of each struct
How to use pointer with struct to refer to the field of each struct

Time:12-28

Below code is the normal way to get the input from a text and store it in an array in a structure.

Wanted to ask how can i use pointer to store all these data into the array of structure ? Like p1->Years (this is without array, but how can i apply this to way of writing in below code)

Any better suggestion to use pointer to take in the input?

int years = 4;
struct maju_company {
    int Year;
    float quarter1, quarter2, quarter3, quarter4, total_sales, average_sales;
};

int main() {
    string line;
    maju_company p1[years];
    fstream yeecinnfile("MajuSales.txt");

    if(yeecinnfile.is_open()) {

        //ignoring the first four line of code and store the rest of the code
        string line1,line2,line3,line4;
        getline(yeecinnfile,line1);
        getline(yeecinnfile,line2);
        getline(yeecinnfile,line3);
        getline(yeecinnfile,line4);
        while(!yeecinnfile.eof()) {
            for(int i =0; i<years; i  ) {
                yeecinnfile>>p1[i].Year>>p1[i].quarter1>>p1[i].quarter2>>p1[i].quarter3>>p1[i].quarter4;
            }

        }

        for(int i =0; i<years; i  ) {
            cout<<p1[i].Year<<setw(10)<<p1[i].quarter1<<setw(10)<<p1[i].quarter2<<setw(10)<<p1[i].quarter3<<setw(10)<<p1[i].quarter4<<endl;
        }


        cout<<endl;
    }
}

CodePudding user response:

I see nothing wrong with the way you do this.

However, you could create a pointer to each record inside the loop

maju_company* p = &p1[i];

and then use p-> instead of p1[i]., but I really don't see this as an improvement.

If the reading loop looks too complicated, I would rather move the code to a separate function, perhaps

void read_record(maju_company& company);

or maybe

maju_company read_record();

and then only have to handle a single company inside the function (so no indexing and no ponters there).

CodePudding user response:

I think you wouldn't need pointers at all for your example. Use a std::vector to hold all your data and then there are other things from C I think you should learn to use, example here : (if you have questions let me know)

#include <iostream>
#include <string>
#include <vector>
#include <fstream>

// dont use : using namespace std;

 struct maju_company_data
 {
     int year;
     float quarter1, quarter2, quarter3, quarter4, total_sales, average_sales;
 };

 // describe how to stream data to an output stream (like std::cout)
 std::ostream& operator<<(std::ostream& os, const maju_company_data& data)
 {
     os << "-----------------------------------------------------\n";
     os << "Company data for year : " << data.year << "\n";
     os << "Quarter 1 : " << data.quarter1 << "\n";
     os << "Quarter 2 : " << data.quarter1 << "\n";
     os << "Quarter 3 : " << data.quarter1 << "\n";
     os << "Quarter 4 : " << data.quarter1 << "\n";
     os << "\n";

     return os;
 }

 int main() 
 {
     // no need to manage pointers yourself use a vector
     std::vector<maju_company_data> company_yearly_data; // give variables a meaningful name
     std::ifstream ifile("MajuSales.txt"); // ifstream your using file as input
     std::string line1, line2, line3, line4;

     // ignore first line
     ifile >> line1;

     while (ifile >> line1 >> line2 >> line3 >> line4) // probably you need to read a few more lines here
     {
         maju_company_data data;

         // convert read strings to numbers
         data.year = std::stoi(line1);
         data.quarter1 = std::stof(line2);
         data.quarter2 = std::stof(line3);
         data.quarter3 = std::stof(line4);
         //..
         //data.quarter4 = std::stof(line5);
         //data.total_sales = std::stof(line6);

         company_yearly_data.push_back(data);
     };

     // this is a range based for loop
     // it is prefered since you cant go out of bounds
     // const auto& means that data will be an unmodifiable
     // reference to each of the structs stored in the vector
     for (const auto& data : company_yearly_data)
     {
         std::cout << data; // since we overloaded << this loop will be nice and clean
     }

     return 0;
}

CodePudding user response:

A C approach to this to overload the istream operator>> and ostream operator<< for your specific type. E.g.

#include <algorithm>
#include <array>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <string>

static constexpr auto years{4};

struct maju_company {
    int Year{};
    float quarter1{}, quarter2{}, quarter3{}, quarter4{};
    float total_sales{}, average_sales{}; // ALWAYS init your floats.
};

auto& operator>>(std::istream& is, maju_company& mc) {
    is >> mc.Year
       >> mc.quarter1 >> mc.quarter2 >> mc.quarter3 >> mc.quarter4
       >> mc.total_sales >> mc.average_sales;
    return is;
}

auto& operator<<(std::ostream& os, maju_company const& mc) {
    os << mc.Year
       << std::setw(10) << mc.quarter1
       << std::setw(10) << mc.quarter2
       << std::setw(10) << mc.quarter3
       << std::setw(10) << mc.quarter4;
    return os;
}

You can then go on to use the type using the std library, e.g.

int main() {
    auto p1{std::array<maju_company, years>{}};
    {
        auto fs{std::fstream("MajuSales.txt")};
        if (!fs.is_open()) return -1;
        {
            // throw away 4 lines
            auto dummy{std::string{}};
            for (auto i{0}; i < 4;   i) getline(fs, dummy);
        }
        std::copy_n(std::istream_iterator<maju_company>{fs},
                    years,
                    begin(p1));
    }
    
    std::copy(cbegin(p1), cend(p1),
              std::ostream_iterator<maju_company>{std::cout, "\n"});
}
  •  Tags:  
  • c
  • Related