miatech
miatech

Reputation: 2278

filling a struct from a text file in C++

guys, I have a text "sales.txt" file which contains (id, lastname, quarter, sales) in the following format.

123 smith 1 333.20
221 doe 1 345.50
342 johnson 1 774.50
123 smith 2 333.20
221 doe 2 555.50
342 johnson 2 25.50
123 smith 3 254.20
221 doe 3 652.50
342 johnson 3 32.50
123 smith 4 354.20
221 doe 4 51.50
342 johnson 4 1000.50

I'm trying to put the file into a struct for output to another text file, but so far I'm having problem with extracting the "id" and lastname. here's a portion of the code. The second method is to extract the sale by quarter and put it into array, but is not working, if someone could give me a hand with both methods

thanks

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

using namespace std;

struct employees { int id; string lname; double qtrSale[4]; double tsale; }; 
void getIdName(employees list[], ifstream& infile, int num);

int main()
{

ifstream infile;
    string file("file1.txt");

    infile.open(file);
    employees list[lsize];
    getIdName(list, infile, lsize);
    /*getData(list, file, lsize);*/

    for(int i = 0; i < lsize; i++)//checking struct
    {
        cout << list[i].id << " " << list[i].lname << endl;
    }
}

void getIdName(employees list[], ifstream& infile, int lsize)
{
    int id; 
    string lname; 
    double sale, temp;

    for(int i = 0; i < lsize; i++)
    {
        infile >> list[i].id >> list[i].lname >> temp >> sale;
        /*for(int j = 1; j <= 4; j++)
        {
            list[i].qtrSale[j] = 0.0;
        }*/

    }
}

void getData(employees list[], string file, int lsize)
{
    int id, qtr; 
    double amount;
    ifstream infile(file);
    while(infile.good())
    {
        for(int j = 0; j < lsize; j++)
        {
            infile >> id;
            for(int i = 1; i <= 4; i++)
            {
                infile >> qtr >> amount;
                if(list[j].id == id && qtr == 1) { list[j].qtrSale[i] = amount; }
                if(list[j].id == id && qtr == 2) { list[j].qtrSale[i] = amount; }
                if(list[j].id == id && qtr == 3) { list[j].qtrSale[i] = amount; }
                if(list[j].id == id && qtr == 4) { list[j].qtrSale[i] = amount; }
            }
        }
    }
}

Upvotes: 1

Views: 4638

Answers (4)

t.g.
t.g.

Reputation: 1749

if you do not mind using boost.spirit. here's how it could be done(tested with vc++2010):

#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>

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

// step 1, define your struct
struct employee
{
    int id;  
    std::string lname; 
    int qtrSale; 
    double tsale; 
};

// step 2, adapt it
BOOST_FUSION_ADAPT_STRUCT(
    employee,
    (int, id)  
    (std::string, lname) 
    (int, qtrSale) 
    (double, tsale) 
)

// step 3, parse it
void parse_file()
{
    using namespace boost::spirit;

    // open file, disable skipping of whitespace
    std::ifstream in("sales.txt");
    in.unsetf(std::ios::skipws);

    std::vector<employee> ve;

    qi::phrase_parse
    (
        // parse from
        istream_iterator(in), 
        // parse to
        istream_iterator(),   
        // reads: an int followed by a ascii string, then by a double and finally by a double, repeatedly at least once.
        +(qi::int_ >> +qi::alpha >> qi::int_ >> qi::double_), 
        // skip all spaces
        qi::ascii::space, 
        // save results to ve
        ve 
    );

    // print the results out
    for(int i = 0; i< ve.size(); i++)
    { 
        std::cout 
             << ve[i].id        << " " 
             << ve[i].lname     << " "   
             << ve[i].qtrSale   << " "    
             << ve[i].tsale     << std::endl; 
    }    
}
    int main()
    {
        parse_file(); 
    }

Upvotes: 1

Maurizio
Maurizio

Reputation: 194

You can use the sscanf function to parse the data. Loop through the file and grab one line at a time then parse the line as follows;

`

    char line []="123 smith 1 333.20" //here for example only
    char strname [20] = { 0 };
    int id = 0;
    int quarter = 0;
    double sales = 0.0;

    sscanf (line,"%d %s %d %f", &id, strname, &quarter, &sales);`

Upvotes: 1

wilhelmtell
wilhelmtell

Reputation: 58685

Study the standard C++ library. The magic is in std::istream_iterator<> from <iterator>, overloading operator>>() for employee and using a std::vector<>:

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

struct employee {
    int id;
    std::string lastname;
    int quarter;
    double sales;
};

template<class Ch, class Tr>
std::basic_istream<Ch,Tr>& operator>>(std::basic_istream<Ch,Tr>& in, employee& e)
{
    return in >> e.id >> e.lastname >> e.quarter >> e.sales;
}

int main(int argc, char* argv[])
{
    std::ifstream infile("sales.txt");
    std::vector<employee> employees((std::istream_iterator<employee>(infile)),
                                    std::istream_iterator<employee>());
    return 0;
}

Upvotes: 4

user470379
user470379

Reputation: 4887

I'm guessing the commented out portion isn't working? In C++ arrays are indexed starting at 0, so that portion should be instead

for(int j=0; j < 4; j++)
{
    list[i].qtrSale[j] = 0.0;
}

Upvotes: 0

Related Questions