1

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;
    }
}
kiner_shah
  • 3,939
  • 7
  • 23
  • 37
code cinn
  • 33
  • 4
  • 2
    It is not clear why you need pointer in this case? Do you want to have an array of pointer? Can you clarify your requirement in more details? – kuro Dec 27 '21 at 09:47
  • You can create a pointer to `p1`, but that is simply a pointer to your array of struct. It would be used just like `p1` itself. During iterations you can assign a pointer to each element, e.g. `maju_company *p = &p1[3];` and now `p` is a pointer to the element you could access as `p->year;`, etc... Aside from something like that, it is unclear what you are asking. – David C. Rankin Dec 27 '21 at 09:47
  • 1
    Probably unrelated: [Why is `iostream::eof()` inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-i-e-while-stream-eof-cons) – Ted Lyngmo Dec 27 '21 at 09:52
  • 1
    [OT]: `for (int i = 0; i != 4; ++i) getline(yeecinnfile, dummyLine);`. – Jarod42 Dec 27 '21 at 10:02
  • for range seems more appropriate than pointer usage. – Jarod42 Dec 27 '21 at 10:03
  • 1
    Please include `MajuSales.txt` in the question (or at least enough of it so that we can see the different parts in it) – Ted Lyngmo Dec 27 '21 at 10:14

3 Answers3

0

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).

BoP
  • 2,310
  • 1
  • 15
  • 24
0

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;
}
Pepijn Kramer
  • 9,356
  • 2
  • 8
  • 19
  • `ifile >> line1;` doesn't read a full line if the line contains whitespaces. – Ted Lyngmo Dec 27 '21 at 10:08
  • 2
    @TedLyngmo True, getline might be better there. Would have helped if file content was part of the question (at least a few lines of it) – Pepijn Kramer Dec 27 '21 at 10:11
  • My main point is still don't use new/delete/pointers unless there is a good reason : use the standard library datastructures if you can and learn about references. – Pepijn Kramer Dec 27 '21 at 10:13
  • You're ignoring the comment in the code _"// ignoring the first four line of code and store the rest of the code"_. Also, `stoi` and `stof` are not necessary for a stream. For most intrinsict types there's an `operator >>` etc defined. – JHBonarius Dec 27 '21 at 10:50
0

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"});
}
JHBonarius
  • 10,824
  • 3
  • 22
  • 41